Cleanup of pc/proxy.h

Avoid implicit conversion from rtc::scoped_refptr to raw pointer, when
calling the MethodCall and ConstMethodCall constructors. Fixed by
defining a private accessor T* c() which always returns a raw pointer,
with different implementation for BEGIN_PROXY_MAP and
BEGIN_OWNED_PROXY_MAP.

Avoid using the same name for macro argument and function argument
within the macro definition, like `c` in:

```
#define PRIMARY_PROXY_MAP_BOILERPLATE(c) \
 protected: \
  c##ProxyWithInternal(rtc::Thread* primary_thread, INTERNAL_CLASS* c) \
      : primary_thread_(primary_thread), c_(c) {} \
```

Fixed by using `class_name` as the macro argument throughout.

Bug: webrtc:13464
Change-Id: I9faf095b004afd5225f5ec09fb782ef4b5c9dc5d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/249089
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35794}
This commit is contained in:
Niels Möller
2022-01-25 16:18:53 +01:00
committed by WebRTC LUCI CQ
parent a36f10bd73
commit 7f761573b3

View File

@ -202,61 +202,66 @@ class ConstMethodCall : public QueuedTask {
#define PROXY_STRINGIZE(x) PROXY_STRINGIZE_IMPL(x) #define PROXY_STRINGIZE(x) PROXY_STRINGIZE_IMPL(x)
// Helper macros to reduce code duplication. // Helper macros to reduce code duplication.
#define PROXY_MAP_BOILERPLATE(c) \ #define PROXY_MAP_BOILERPLATE(class_name) \
template <class INTERNAL_CLASS> \ template <class INTERNAL_CLASS> \
class c##ProxyWithInternal; \ class class_name##ProxyWithInternal; \
typedef c##ProxyWithInternal<c##Interface> c##Proxy; \ typedef class_name##ProxyWithInternal<class_name##Interface> \
template <class INTERNAL_CLASS> \ class_name##Proxy; \
class c##ProxyWithInternal : public c##Interface { \ template <class INTERNAL_CLASS> \
protected: \ class class_name##ProxyWithInternal : public class_name##Interface { \
static constexpr char proxy_name_[] = #c "Proxy"; \ protected: \
typedef c##Interface C; \ static constexpr char proxy_name_[] = #class_name "Proxy"; \
\ typedef class_name##Interface C; \
public: \ \
const INTERNAL_CLASS* internal() const { return c_; } \ public: \
INTERNAL_CLASS* internal() { return c_; } const INTERNAL_CLASS* internal() const { return c(); } \
INTERNAL_CLASS* internal() { return c(); }
// clang-format off // clang-format off
// clang-format would put the semicolon alone, // clang-format would put the semicolon alone,
// leading to a presubmit error (cpplint.py) // leading to a presubmit error (cpplint.py)
#define END_PROXY_MAP(c) \ #define END_PROXY_MAP(class_name) \
}; \ }; \
template <class INTERNAL_CLASS> \ template <class INTERNAL_CLASS> \
constexpr char c##ProxyWithInternal<INTERNAL_CLASS>::proxy_name_[]; constexpr char class_name##ProxyWithInternal<INTERNAL_CLASS>::proxy_name_[];
// clang-format on // clang-format on
#define PRIMARY_PROXY_MAP_BOILERPLATE(c) \ #define PRIMARY_PROXY_MAP_BOILERPLATE(class_name) \
protected: \ protected: \
c##ProxyWithInternal(rtc::Thread* primary_thread, INTERNAL_CLASS* c) \ class_name##ProxyWithInternal(rtc::Thread* primary_thread, \
: primary_thread_(primary_thread), c_(c) {} \ INTERNAL_CLASS* c) \
\ : primary_thread_(primary_thread), c_(c) {} \
private: \ \
private: \
mutable rtc::Thread* primary_thread_; mutable rtc::Thread* primary_thread_;
#define SECONDARY_PROXY_MAP_BOILERPLATE(c) \ #define SECONDARY_PROXY_MAP_BOILERPLATE(class_name) \
protected: \ protected: \
c##ProxyWithInternal(rtc::Thread* primary_thread, \ class_name##ProxyWithInternal(rtc::Thread* primary_thread, \
rtc::Thread* secondary_thread, INTERNAL_CLASS* c) \ rtc::Thread* secondary_thread, \
: primary_thread_(primary_thread), \ INTERNAL_CLASS* c) \
secondary_thread_(secondary_thread), \ : primary_thread_(primary_thread), \
c_(c) {} \ secondary_thread_(secondary_thread), \
\ c_(c) {} \
private: \ \
mutable rtc::Thread* primary_thread_; \ private: \
mutable rtc::Thread* primary_thread_; \
mutable rtc::Thread* secondary_thread_; mutable rtc::Thread* secondary_thread_;
// Note that the destructor is protected so that the proxy can only be // Note that the destructor is protected so that the proxy can only be
// destroyed via RefCountInterface. // destroyed via RefCountInterface.
#define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ #define REFCOUNTED_PROXY_MAP_BOILERPLATE(class_name) \
protected: \ protected: \
~c##ProxyWithInternal() { \ ~class_name##ProxyWithInternal() { \
MethodCall<c##ProxyWithInternal, void> call( \ MethodCall<class_name##ProxyWithInternal, void> call( \
this, &c##ProxyWithInternal::DestroyInternal); \ this, &class_name##ProxyWithInternal::DestroyInternal); \
call.Marshal(RTC_FROM_HERE, destructor_thread()); \ call.Marshal(RTC_FROM_HERE, destructor_thread()); \
} \ } \
\ \
private: \ private: \
void DestroyInternal() { c_ = nullptr; } \ const INTERNAL_CLASS* c() const { return c_.get(); } \
INTERNAL_CLASS* c() { return c_.get(); } \
void DestroyInternal() { c_ = nullptr; } \
rtc::scoped_refptr<INTERNAL_CLASS> c_; rtc::scoped_refptr<INTERNAL_CLASS> c_;
// Note: This doesn't use a unique_ptr, because it intends to handle a corner // Note: This doesn't use a unique_ptr, because it intends to handle a corner
@ -264,50 +269,54 @@ class ConstMethodCall : public QueuedTask {
// this proxy object. If relying on a unique_ptr to delete the object, its // this proxy object. If relying on a unique_ptr to delete the object, its
// inner pointer would be set to null before this reentrant callback would have // inner pointer would be set to null before this reentrant callback would have
// a chance to run, resulting in a segfault. // a chance to run, resulting in a segfault.
#define OWNED_PROXY_MAP_BOILERPLATE(c) \ #define OWNED_PROXY_MAP_BOILERPLATE(class_name) \
public: \ public: \
~c##ProxyWithInternal() { \ ~class_name##ProxyWithInternal() { \
MethodCall<c##ProxyWithInternal, void> call( \ MethodCall<class_name##ProxyWithInternal, void> call( \
this, &c##ProxyWithInternal::DestroyInternal); \ this, &class_name##ProxyWithInternal::DestroyInternal); \
call.Marshal(RTC_FROM_HERE, destructor_thread()); \ call.Marshal(RTC_FROM_HERE, destructor_thread()); \
} \ } \
\ \
private: \ private: \
void DestroyInternal() { delete c_; } \ const INTERNAL_CLASS* c() const { return c_; } \
INTERNAL_CLASS* c() { return c_; } \
void DestroyInternal() { delete c_; } \
INTERNAL_CLASS* c_; INTERNAL_CLASS* c_;
#define BEGIN_PRIMARY_PROXY_MAP(c) \ #define BEGIN_PRIMARY_PROXY_MAP(class_name) \
PROXY_MAP_BOILERPLATE(c) \ PROXY_MAP_BOILERPLATE(class_name) \
PRIMARY_PROXY_MAP_BOILERPLATE(c) \ PRIMARY_PROXY_MAP_BOILERPLATE(class_name) \
REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ REFCOUNTED_PROXY_MAP_BOILERPLATE(class_name) \
public: \
static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
rtc::Thread* primary_thread, INTERNAL_CLASS* c) { \
return rtc::make_ref_counted<c##ProxyWithInternal>(primary_thread, c); \
}
#define BEGIN_PROXY_MAP(c) \
PROXY_MAP_BOILERPLATE(c) \
SECONDARY_PROXY_MAP_BOILERPLATE(c) \
REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
public: \
static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
rtc::Thread* primary_thread, rtc::Thread* secondary_thread, \
INTERNAL_CLASS* c) { \
return rtc::make_ref_counted<c##ProxyWithInternal>(primary_thread, \
secondary_thread, c); \
}
#define BEGIN_OWNED_PROXY_MAP(c) \
PROXY_MAP_BOILERPLATE(c) \
SECONDARY_PROXY_MAP_BOILERPLATE(c) \
OWNED_PROXY_MAP_BOILERPLATE(c) \
public: \ public: \
static std::unique_ptr<c##Interface> Create( \ static rtc::scoped_refptr<class_name##ProxyWithInternal> Create( \
rtc::Thread* primary_thread, INTERNAL_CLASS* c) { \
return rtc::make_ref_counted<class_name##ProxyWithInternal>( \
primary_thread, c); \
}
#define BEGIN_PROXY_MAP(class_name) \
PROXY_MAP_BOILERPLATE(class_name) \
SECONDARY_PROXY_MAP_BOILERPLATE(class_name) \
REFCOUNTED_PROXY_MAP_BOILERPLATE(class_name) \
public: \
static rtc::scoped_refptr<class_name##ProxyWithInternal> Create( \
rtc::Thread* primary_thread, rtc::Thread* secondary_thread, \ rtc::Thread* primary_thread, rtc::Thread* secondary_thread, \
std::unique_ptr<INTERNAL_CLASS> c) { \ INTERNAL_CLASS* c) { \
return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \ return rtc::make_ref_counted<class_name##ProxyWithInternal>( \
primary_thread, secondary_thread, c.release())); \ primary_thread, secondary_thread, c); \
}
#define BEGIN_OWNED_PROXY_MAP(class_name) \
PROXY_MAP_BOILERPLATE(class_name) \
SECONDARY_PROXY_MAP_BOILERPLATE(class_name) \
OWNED_PROXY_MAP_BOILERPLATE(class_name) \
public: \
static std::unique_ptr<class_name##Interface> Create( \
rtc::Thread* primary_thread, rtc::Thread* secondary_thread, \
std::unique_ptr<INTERNAL_CLASS> c) { \
return std::unique_ptr<class_name##Interface>( \
new class_name##ProxyWithInternal(primary_thread, secondary_thread, \
c.release())); \
} }
#define PROXY_PRIMARY_THREAD_DESTRUCTOR() \ #define PROXY_PRIMARY_THREAD_DESTRUCTOR() \
@ -339,124 +348,124 @@ class ConstMethodCall : public QueuedTask {
#define PROXY_METHOD0(r, method) \ #define PROXY_METHOD0(r, method) \
r method() override { \ r method() override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r> call(c_, &C::method); \ MethodCall<C, r> call(c(), &C::method); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_CONSTMETHOD0(r, method) \ #define PROXY_CONSTMETHOD0(r, method) \
r method() const override { \ r method() const override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r> call(c_, &C::method); \ ConstMethodCall<C, r> call(c(), &C::method); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_METHOD1(r, method, t1) \ #define PROXY_METHOD1(r, method, t1) \
r method(t1 a1) override { \ r method(t1 a1) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \ MethodCall<C, r, t1> call(c(), &C::method, std::move(a1)); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_CONSTMETHOD1(r, method, t1) \ #define PROXY_CONSTMETHOD1(r, method, t1) \
r method(t1 a1) const override { \ r method(t1 a1) const override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \ ConstMethodCall<C, r, t1> call(c(), &C::method, std::move(a1)); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_METHOD2(r, method, t1, t2) \ #define PROXY_METHOD2(r, method, t1, t2) \
r method(t1 a1, t2 a2) override { \ r method(t1 a1, t2 a2) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \ MethodCall<C, r, t1, t2> call(c(), &C::method, std::move(a1), \
std::move(a2)); \ std::move(a2)); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_METHOD3(r, method, t1, t2, t3) \ #define PROXY_METHOD3(r, method, t1, t2, t3) \
r method(t1 a1, t2 a2, t3 a3) override { \ r method(t1 a1, t2 a2, t3 a3) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \ MethodCall<C, r, t1, t2, t3> call(c(), &C::method, std::move(a1), \
std::move(a2), std::move(a3)); \ std::move(a2), std::move(a3)); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \ #define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \ r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1, t2, t3, t4> call(c_, &C::method, std::move(a1), \ MethodCall<C, r, t1, t2, t3, t4> call(c(), &C::method, std::move(a1), \
std::move(a2), std::move(a3), \ std::move(a2), std::move(a3), \
std::move(a4)); \ std::move(a4)); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \ #define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \ r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1, t2, t3, t4, t5> call(c_, &C::method, std::move(a1), \ MethodCall<C, r, t1, t2, t3, t4, t5> call(c(), &C::method, std::move(a1), \
std::move(a2), std::move(a3), \ std::move(a2), std::move(a3), \
std::move(a4), std::move(a5)); \ std::move(a4), std::move(a5)); \
return call.Marshal(RTC_FROM_HERE, primary_thread_); \ return call.Marshal(RTC_FROM_HERE, primary_thread_); \
} }
// Define methods which should be invoked on the secondary thread. // Define methods which should be invoked on the secondary thread.
#define PROXY_SECONDARY_METHOD0(r, method) \ #define PROXY_SECONDARY_METHOD0(r, method) \
r method() override { \ r method() override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r> call(c_, &C::method); \ MethodCall<C, r> call(c(), &C::method); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
#define PROXY_SECONDARY_CONSTMETHOD0(r, method) \ #define PROXY_SECONDARY_CONSTMETHOD0(r, method) \
r method() const override { \ r method() const override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r> call(c_, &C::method); \ ConstMethodCall<C, r> call(c(), &C::method); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
#define PROXY_SECONDARY_METHOD1(r, method, t1) \ #define PROXY_SECONDARY_METHOD1(r, method, t1) \
r method(t1 a1) override { \ r method(t1 a1) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \ MethodCall<C, r, t1> call(c(), &C::method, std::move(a1)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
#define PROXY_SECONDARY_CONSTMETHOD1(r, method, t1) \ #define PROXY_SECONDARY_CONSTMETHOD1(r, method, t1) \
r method(t1 a1) const override { \ r method(t1 a1) const override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \ ConstMethodCall<C, r, t1> call(c(), &C::method, std::move(a1)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
#define PROXY_SECONDARY_METHOD2(r, method, t1, t2) \ #define PROXY_SECONDARY_METHOD2(r, method, t1, t2) \
r method(t1 a1, t2 a2) override { \ r method(t1 a1, t2 a2) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \ MethodCall<C, r, t1, t2> call(c(), &C::method, std::move(a1), \
std::move(a2)); \ std::move(a2)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
#define PROXY_SECONDARY_CONSTMETHOD2(r, method, t1, t2) \ #define PROXY_SECONDARY_CONSTMETHOD2(r, method, t1, t2) \
r method(t1 a1, t2 a2) const override { \ r method(t1 a1, t2 a2) const override { \
TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r, t1, t2> call(c(), &C::method, std::move(a1), \
std::move(a2)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
}
#define PROXY_SECONDARY_METHOD3(r, method, t1, t2, t3) \
r method(t1 a1, t2 a2, t3 a3) override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \ MethodCall<C, r, t1, t2, t3> call(c(), &C::method, std::move(a1), \
std::move(a2)); \ std::move(a2), std::move(a3)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
#define PROXY_SECONDARY_METHOD3(r, method, t1, t2, t3) \ #define PROXY_SECONDARY_CONSTMETHOD3(r, method, t1, t2) \
r method(t1 a1, t2 a2, t3 a3) override { \ r method(t1 a1, t2 a2, t3 a3) const override { \
TRACE_BOILERPLATE(method); \ TRACE_BOILERPLATE(method); \
MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \ ConstMethodCall<C, r, t1, t2, t3> call(c(), &C::method, std::move(a1), \
std::move(a2), std::move(a3)); \ std::move(a2), std::move(a3)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \ return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
}
#define PROXY_SECONDARY_CONSTMETHOD3(r, method, t1, t2) \
r method(t1 a1, t2 a2, t3 a3) const override { \
TRACE_BOILERPLATE(method); \
ConstMethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
std::move(a2), std::move(a3)); \
return call.Marshal(RTC_FROM_HERE, secondary_thread_); \
} }
// For use when returning purely const state (set during construction). // For use when returning purely const state (set during construction).