mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 1634846 - P3. Get around NS_INLINE_DECL_REFCOUNTING not working with TaskQueue. r=nika,froydnj
NS_INLINE_DECL_REFCOUNTING macro doesn't properly work when the object is used on a thread that isn't backed by a single PRThread (such as TaskQueue). See bug 1648031. The resolution of this issue is rather complex, and outside the scope of this series of change. So for now, we create a new macro NS_INLINE_DECL_REFCOUNTING_ONEVENTTHREAD which will use a different mechanism to ensure the thread-safe usage of a class. Differential Revision: https://phabricator.services.mozilla.com/D81269
This commit is contained in:
parent
b2cf09ec3e
commit
afea3c617d
@ -860,7 +860,7 @@ class ManagedEndpoint {
|
||||
// references!
|
||||
class ActorLifecycleProxy {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(ActorLifecycleProxy)
|
||||
NS_INLINE_DECL_REFCOUNTING_ONEVENTTARGET(ActorLifecycleProxy)
|
||||
|
||||
IProtocol* Get() { return mActor; }
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
|
||||
# include "nsThreadUtils.h"
|
||||
@ -44,4 +45,26 @@ void nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const {
|
||||
bool nsAutoOwningThread::IsCurrentThread() const {
|
||||
return mThread == PR_GetCurrentThread();
|
||||
}
|
||||
|
||||
nsAutoOwningEventTarget::nsAutoOwningEventTarget()
|
||||
: mTarget(GetCurrentSerialEventTarget()) {
|
||||
mTarget->AddRef();
|
||||
}
|
||||
|
||||
nsAutoOwningEventTarget::~nsAutoOwningEventTarget() {
|
||||
nsCOMPtr<nsISerialEventTarget> target = dont_AddRef(mTarget);
|
||||
}
|
||||
|
||||
void nsAutoOwningEventTarget ::AssertCurrentThreadOwnsMe(
|
||||
const char* msg) const {
|
||||
if (MOZ_UNLIKELY(!IsCurrentThread())) {
|
||||
// `msg` is a string literal by construction.
|
||||
MOZ_CRASH_UNSAFE(msg);
|
||||
}
|
||||
}
|
||||
|
||||
bool nsAutoOwningEventTarget::IsCurrentThread() const {
|
||||
return mTarget->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -68,12 +68,38 @@ class nsAutoOwningThread {
|
||||
void* mThread;
|
||||
};
|
||||
|
||||
class nsISerialEventTarget;
|
||||
class nsAutoOwningEventTarget {
|
||||
public:
|
||||
nsAutoOwningEventTarget();
|
||||
~nsAutoOwningEventTarget();
|
||||
|
||||
// We move the actual assertion checks out-of-line to minimize code bloat,
|
||||
// but that means we have to pass a non-literal string to MOZ_CRASH_UNSAFE.
|
||||
// To make that more safe, the public interface requires a literal string
|
||||
// and passes that to the private interface; we can then be assured that we
|
||||
// effectively are passing a literal string to MOZ_CRASH_UNSAFE.
|
||||
template <int N>
|
||||
void AssertOwnership(const char (&aMsg)[N]) const {
|
||||
AssertCurrentThreadOwnsMe(aMsg);
|
||||
}
|
||||
|
||||
bool IsCurrentThread() const;
|
||||
|
||||
private:
|
||||
void AssertCurrentThreadOwnsMe(const char* aMsg) const;
|
||||
|
||||
nsISerialEventTarget* mTarget;
|
||||
};
|
||||
|
||||
# define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread;
|
||||
# define NS_DECL_OWNINGEVENTTARGET nsAutoOwningEventTarget _mOwningThread;
|
||||
# define NS_ASSERT_OWNINGTHREAD(_class) \
|
||||
_mOwningThread.AssertOwnership(#_class " not thread-safe")
|
||||
#else // !MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
|
||||
|
||||
# define NS_DECL_OWNINGTHREAD /* nothing */
|
||||
# define NS_DECL_OWNINGEVENTTARGET /* nothing */
|
||||
# define NS_ASSERT_OWNINGTHREAD(_class) ((void)0)
|
||||
|
||||
#endif // MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
|
||||
@ -567,33 +593,33 @@ class ThreadSafeAutoRefCnt {
|
||||
* AddRef & Release methods (typically NS_IMETHOD_ or NS_METHOD_).
|
||||
* @param optional override Mark the AddRef & Release methods as overrides.
|
||||
*/
|
||||
#define NS_INLINE_DECL_REFCOUNTING_META(_class, _decl, _destroy, ...) \
|
||||
public: \
|
||||
_decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
|
||||
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
|
||||
NS_ASSERT_OWNINGTHREAD(_class); \
|
||||
++mRefCnt; \
|
||||
NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
|
||||
return mRefCnt; \
|
||||
} \
|
||||
_decl(MozExternalRefCountType) Release(void) __VA_ARGS__ { \
|
||||
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
|
||||
NS_ASSERT_OWNINGTHREAD(_class); \
|
||||
--mRefCnt; \
|
||||
NS_LOG_RELEASE(this, mRefCnt, #_class); \
|
||||
if (mRefCnt == 0) { \
|
||||
mRefCnt = 1; /* stabilize */ \
|
||||
_destroy; \
|
||||
return 0; \
|
||||
} \
|
||||
return mRefCnt; \
|
||||
} \
|
||||
using HasThreadSafeRefCnt = std::false_type; \
|
||||
\
|
||||
protected: \
|
||||
nsAutoRefCnt mRefCnt; \
|
||||
NS_DECL_OWNINGTHREAD \
|
||||
#define NS_INLINE_DECL_REFCOUNTING_META(_class, _decl, _destroy, _owning, ...) \
|
||||
public: \
|
||||
_decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
|
||||
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
|
||||
NS_ASSERT_OWNINGTHREAD(_class); \
|
||||
++mRefCnt; \
|
||||
NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
|
||||
return mRefCnt; \
|
||||
} \
|
||||
_decl(MozExternalRefCountType) Release(void) __VA_ARGS__ { \
|
||||
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
|
||||
NS_ASSERT_OWNINGTHREAD(_class); \
|
||||
--mRefCnt; \
|
||||
NS_LOG_RELEASE(this, mRefCnt, #_class); \
|
||||
if (mRefCnt == 0) { \
|
||||
mRefCnt = 1; /* stabilize */ \
|
||||
_destroy; \
|
||||
return 0; \
|
||||
} \
|
||||
return mRefCnt; \
|
||||
} \
|
||||
using HasThreadSafeRefCnt = std::false_type; \
|
||||
\
|
||||
protected: \
|
||||
nsAutoRefCnt mRefCnt; \
|
||||
_owning \
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -606,14 +632,16 @@ class ThreadSafeAutoRefCnt {
|
||||
* @param optional override Mark the AddRef & Release methods as overrides.
|
||||
*/
|
||||
#define NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, _destroy, ...) \
|
||||
NS_INLINE_DECL_REFCOUNTING_META(_class, NS_METHOD_, _destroy, __VA_ARGS__)
|
||||
NS_INLINE_DECL_REFCOUNTING_META(_class, NS_METHOD_, _destroy, \
|
||||
NS_DECL_OWNINGTHREAD, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Like NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY with AddRef & Release declared
|
||||
* virtual.
|
||||
*/
|
||||
#define NS_INLINE_DECL_VIRTUAL_REFCOUNTING_WITH_DESTROY(_class, _destroy, ...) \
|
||||
NS_INLINE_DECL_REFCOUNTING_META(_class, NS_IMETHOD_, _destroy, __VA_ARGS__)
|
||||
NS_INLINE_DECL_REFCOUNTING_META(_class, NS_IMETHOD_, _destroy, \
|
||||
NS_DECL_OWNINGTHREAD, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Use this macro to declare and implement the AddRef & Release methods for a
|
||||
@ -625,6 +653,16 @@ class ThreadSafeAutoRefCnt {
|
||||
#define NS_INLINE_DECL_REFCOUNTING(_class, ...) \
|
||||
NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, delete (this), __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Like NS_INLINE_DECL_REFCOUNTING, however the thread safety check will work
|
||||
* with any nsISerialEventTarget. This is a workaround until bug 1648031 is
|
||||
* properly resolved. Once this is done, it will be possible to use
|
||||
* NS_INLINE_DECL_REFCOUNTING under all circumstances.
|
||||
*/
|
||||
#define NS_INLINE_DECL_REFCOUNTING_ONEVENTTARGET(_class, ...) \
|
||||
NS_INLINE_DECL_REFCOUNTING_META(_class, NS_METHOD_, delete (this), \
|
||||
NS_DECL_OWNINGEVENTTARGET, __VA_ARGS__)
|
||||
|
||||
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, _destroy, \
|
||||
...) \
|
||||
public: \
|
||||
|
Loading…
Reference in New Issue
Block a user