diff --git a/api/BUILD.gn b/api/BUILD.gn index 1c1731ee32..b0822142ea 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -262,6 +262,15 @@ rtc_source_set("optional") { ] } +rtc_source_set("refcountedbase") { + sources = [ + "refcountedbase.h", + ] + deps = [ + "../rtc_base:rtc_base_approved", + ] +} + rtc_source_set("libjingle_peerconnection_test_api") { testonly = true sources = [ diff --git a/api/refcountedbase.h b/api/refcountedbase.h new file mode 100644 index 0000000000..8c26efd3e3 --- /dev/null +++ b/api/refcountedbase.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 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. + */ +#ifndef API_REFCOUNTEDBASE_H_ +#define API_REFCOUNTEDBASE_H_ + +#include "rtc_base/constructormagic.h" +#include "rtc_base/refcount.h" +#include "rtc_base/refcounter.h" + +namespace rtc { + +class RefCountedBase { + public: + RefCountedBase() = default; + + void AddRef() const { ref_count_.IncRef(); } + RefCountReleaseStatus Release() const { + const auto status = ref_count_.DecRef(); + if (status == RefCountReleaseStatus::kDroppedLastRef) { + delete this; + } + return status; + } + + protected: + virtual ~RefCountedBase() = default; + + private: + mutable webrtc::webrtc_impl::RefCounter ref_count_{0}; + + RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedBase); +}; + +} // namespace rtc + +#endif // API_REFCOUNTEDBASE_H_ diff --git a/audio/audio_state.h b/audio/audio_state.h index bdec529cd8..86d60b6813 100644 --- a/audio/audio_state.h +++ b/audio/audio_state.h @@ -50,6 +50,7 @@ class AudioState final : public webrtc::AudioState { ScopedVoEInterface voe_base_; // Reference count; implementation copied from rtc::RefCountedObject. + // TODO(nisse): Use RefCountedObject or RefCountedBase instead. mutable volatile int ref_count_ = 0; // Transports mixed audio from the mixer to the audio device and diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn index a87cbc1200..b63ebb6915 100644 --- a/modules/desktop_capture/BUILD.gn +++ b/modules/desktop_capture/BUILD.gn @@ -337,6 +337,7 @@ rtc_static_library("desktop_capture_generic") { deps = [ ":primitives", "../..:webrtc_common", + "../../api:refcountedbase", "../../rtc_base:rtc_base", # TODO(kjellander): Cleanup in bugs.webrtc.org/3806. "../../system_wrappers", "//third_party/libyuv", diff --git a/modules/desktop_capture/mac/desktop_configuration_monitor.cc b/modules/desktop_capture/mac/desktop_configuration_monitor.cc index c8cc916d59..b8bcdd94fc 100644 --- a/modules/desktop_capture/mac/desktop_configuration_monitor.cc +++ b/modules/desktop_capture/mac/desktop_configuration_monitor.cc @@ -20,8 +20,7 @@ namespace webrtc { static const int64_t kDisplayConfigurationEventTimeoutMs = 10 * 1000; DesktopConfigurationMonitor::DesktopConfigurationMonitor() - : ref_count_(0), - display_configuration_capture_event_(EventWrapper::Create()) { + : display_configuration_capture_event_(EventWrapper::Create()) { CGError err = CGDisplayRegisterReconfigurationCallback( DesktopConfigurationMonitor::DisplaysReconfiguredCallback, this); if (err != kCGErrorSuccess) { diff --git a/modules/desktop_capture/mac/desktop_configuration_monitor.h b/modules/desktop_capture/mac/desktop_configuration_monitor.h index 3cb5009a32..746fbb271d 100644 --- a/modules/desktop_capture/mac/desktop_configuration_monitor.h +++ b/modules/desktop_capture/mac/desktop_configuration_monitor.h @@ -16,9 +16,9 @@ #include #include +#include "api/refcountedbase.h" #include "modules/desktop_capture/mac/desktop_configuration.h" #include "rtc_base/constructormagic.h" -#include "system_wrappers/include/atomic32.h" namespace webrtc { @@ -26,7 +26,7 @@ class EventWrapper; // The class provides functions to synchronize capturing and display // reconfiguring across threads, and the up-to-date MacDesktopConfiguration. -class DesktopConfigurationMonitor { +class DesktopConfigurationMonitor : public rtc::RefCountedBase { public: DesktopConfigurationMonitor(); // Acquires a lock on the current configuration. @@ -39,22 +39,16 @@ class DesktopConfigurationMonitor { return desktop_configuration_; } - void AddRef() { ++ref_count_; } - void Release() { - if (--ref_count_ == 0) - delete this; - } + protected: + ~DesktopConfigurationMonitor() override; private: static void DisplaysReconfiguredCallback(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *user_parameter); - ~DesktopConfigurationMonitor(); - void DisplaysReconfigured(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags); - Atomic32 ref_count_; std::set reconfiguring_displays_; MacDesktopConfiguration desktop_configuration_; std::unique_ptr display_configuration_capture_event_; diff --git a/modules/desktop_capture/mac/full_screen_chrome_window_detector.cc b/modules/desktop_capture/mac/full_screen_chrome_window_detector.cc index b5ba988c04..96786ad2e6 100644 --- a/modules/desktop_capture/mac/full_screen_chrome_window_detector.cc +++ b/modules/desktop_capture/mac/full_screen_chrome_window_detector.cc @@ -141,7 +141,7 @@ bool IsChromeWindow(CGWindowID id) { } // namespace FullScreenChromeWindowDetector::FullScreenChromeWindowDetector() - : ref_count_(0), last_update_time_ns_(0) {} + : last_update_time_ns_(0) {} FullScreenChromeWindowDetector::~FullScreenChromeWindowDetector() {} diff --git a/modules/desktop_capture/mac/full_screen_chrome_window_detector.h b/modules/desktop_capture/mac/full_screen_chrome_window_detector.h index b03521bf34..4fbe0009eb 100644 --- a/modules/desktop_capture/mac/full_screen_chrome_window_detector.h +++ b/modules/desktop_capture/mac/full_screen_chrome_window_detector.h @@ -13,9 +13,9 @@ #include +#include "api/refcountedbase.h" #include "modules/desktop_capture/desktop_capturer.h" #include "rtc_base/constructormagic.h" -#include "system_wrappers/include/atomic32.h" namespace webrtc { @@ -30,16 +30,10 @@ namespace webrtc { // 3. The new window is full-screen. // 4. The new window didn't exist at least 500 millisecond ago. -class FullScreenChromeWindowDetector { +class FullScreenChromeWindowDetector : public rtc::RefCountedBase { public: FullScreenChromeWindowDetector(); - void AddRef() { ++ref_count_; } - void Release() { - if (--ref_count_ == 0) - delete this; - } - // Returns the full-screen window in place of the original window if all the // criteria are met, or kCGNullWindowID if no such window found. CGWindowID FindFullScreenWindow(CGWindowID original_window); @@ -48,11 +42,10 @@ class FullScreenChromeWindowDetector { // second. void UpdateWindowListIfNeeded(CGWindowID original_window); + protected: + ~FullScreenChromeWindowDetector() override; + private: - ~FullScreenChromeWindowDetector(); - - Atomic32 ref_count_; - // We cache the last two results of the window list, so // |previous_window_list_| is taken at least 500ms before the next Capture() // call. If we only save the last result, we may get false positive (i.e. diff --git a/modules/desktop_capture/window_capturer_x11.cc b/modules/desktop_capture/window_capturer_x11.cc index 78153161e0..dc1c6faffe 100644 --- a/modules/desktop_capture/window_capturer_x11.cc +++ b/modules/desktop_capture/window_capturer_x11.cc @@ -8,6 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include + #include #include #include diff --git a/modules/desktop_capture/x11/shared_x_display.h b/modules/desktop_capture/x11/shared_x_display.h index 8b888de014..4d93b3b175 100644 --- a/modules/desktop_capture/x11/shared_x_display.h +++ b/modules/desktop_capture/x11/shared_x_display.h @@ -16,9 +16,9 @@ #include +#include "api/refcountedbase.h" #include "rtc_base/constructormagic.h" #include "rtc_base/scoped_ref_ptr.h" -#include "system_wrappers/include/atomic32.h" // Including Xlib.h will involve evil defines (Bool, Status, True, False), which // easily conflict with other headers. @@ -28,7 +28,7 @@ typedef union _XEvent XEvent; namespace webrtc { // A ref-counted object to store XDisplay connection. -class SharedXDisplay { +class SharedXDisplay : public rtc::RefCountedBase { public: class XEventHandler { public: @@ -51,12 +51,6 @@ class SharedXDisplay { // DISPLAY). NULL is returned if X11 connection failed. static rtc::scoped_refptr CreateDefault(); - void AddRef() { ++ref_count_; } - void Release() { - if (--ref_count_ == 0) - delete this; - } - Display* display() { return display_; } // Adds a new event |handler| for XEvent's of |type|. @@ -69,12 +63,12 @@ class SharedXDisplay { // Processes pending XEvents, calling corresponding event handlers. void ProcessPendingXEvents(); + protected: + ~SharedXDisplay() override; + private: typedef std::map > EventHandlersMap; - ~SharedXDisplay(); - - Atomic32 ref_count_; Display* display_; EventHandlersMap event_handlers_; diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 443d32ef80..710de7af8d 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -167,6 +167,7 @@ rtc_source_set("rtc_base_approved_generic") { "ratetracker.h", "refcount.h", "refcountedobject.h", + "refcounter.h", "safe_compare.h", "safe_conversions.h", "safe_conversions_impl.h", diff --git a/rtc_base/refcountedobject.h b/rtc_base/refcountedobject.h index f04b7f974c..da3ed9ff2f 100644 --- a/rtc_base/refcountedobject.h +++ b/rtc_base/refcountedobject.h @@ -12,8 +12,9 @@ #include -#include "rtc_base/atomicops.h" +#include "rtc_base/constructormagic.h" #include "rtc_base/refcount.h" +#include "rtc_base/refcounter.h" namespace rtc { @@ -31,14 +32,14 @@ class RefCountedObject : public T { std::forward(p1), std::forward(args)...) {} - virtual void AddRef() const { AtomicOps::Increment(&ref_count_); } + virtual void AddRef() const { ref_count_.IncRef(); } virtual RefCountReleaseStatus Release() const { - if (AtomicOps::Decrement(&ref_count_) == 0) { + const auto status = ref_count_.DecRef(); + if (status == RefCountReleaseStatus::kDroppedLastRef) { delete this; - return RefCountReleaseStatus::kDroppedLastRef; } - return RefCountReleaseStatus::kOtherRefsRemained; + return status; } // Return whether the reference count is one. If the reference count is used @@ -47,14 +48,14 @@ class RefCountedObject : public T { // 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; - } + virtual bool HasOneRef() const { return ref_count_.HasOneRef(); } protected: virtual ~RefCountedObject() {} - mutable volatile int ref_count_ = 0; + mutable webrtc::webrtc_impl::RefCounter ref_count_{0}; + + RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedObject); }; } // namespace rtc diff --git a/rtc_base/refcounter.h b/rtc_base/refcounter.h new file mode 100644 index 0000000000..baf72ae2a0 --- /dev/null +++ b/rtc_base/refcounter.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 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. + */ +#ifndef RTC_BASE_REFCOUNTER_H_ +#define RTC_BASE_REFCOUNTER_H_ + +#include "rtc_base/atomicops.h" +#include "rtc_base/refcount.h" + +namespace webrtc { +namespace webrtc_impl { + +class RefCounter { + public: + explicit RefCounter(int ref_count) : ref_count_(ref_count) {} + RefCounter() = delete; + + void IncRef() { rtc::AtomicOps::Increment(&ref_count_); } + + // TODO(nisse): Switch return type to RefCountReleaseStatus? + // Returns true if this was the last reference, and the resource protected by + // the reference counter can be deleted. + rtc::RefCountReleaseStatus DecRef() { + return (rtc::AtomicOps::Decrement(&ref_count_) == 0) + ? rtc::RefCountReleaseStatus::kDroppedLastRef + : rtc::RefCountReleaseStatus::kOtherRefsRemained; + } + + // 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 resource protected by the + // reference counter, knowing that it has exclusive access. + bool HasOneRef() const { + return rtc::AtomicOps::AcquireLoad(&ref_count_) == 1; + } + + private: + volatile int ref_count_; +}; + +} // namespace webrtc_impl +} // namespace webrtc + +#endif // RTC_BASE_REFCOUNTER_H_