summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h')
-rw-r--r--gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h91
1 files changed, 91 insertions, 0 deletions
diff --git a/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h b/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h
new file mode 100644
index 000000000..e64705478
--- /dev/null
+++ b/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h
@@ -0,0 +1,91 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
+#define THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
+
+#include "base/message_loop.h"
+#include "MainThreadUtils.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace layers {
+
+inline MessageLoop* GetMainLoopAssertingMainThread()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ return MessageLoop::current();
+}
+
+inline MessageLoop* GetMainLoop()
+{
+ static MessageLoop* sMainLoop = GetMainLoopAssertingMainThread();
+ return sMainLoop;
+}
+
+struct HelperForMainThreadDestruction
+{
+ HelperForMainThreadDestruction()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ GetMainLoop();
+ }
+
+ ~HelperForMainThreadDestruction()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ }
+};
+
+template<typename T>
+struct DeleteOnMainThreadTask : public Runnable
+{
+ T* mToDelete;
+ explicit DeleteOnMainThreadTask(T* aToDelete) : mToDelete(aToDelete) {}
+ NS_IMETHOD Run() override {
+ MOZ_ASSERT(NS_IsMainThread());
+ mToDelete->DeleteToBeCalledOnMainThread();
+ return NS_OK;
+ }
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(_class) \
+public: \
+ NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
+ MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
+ MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
+ nsrefcnt count = ++mRefCnt; \
+ NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
+ return (nsrefcnt) count; \
+ } \
+ void DeleteToBeCalledOnMainThread() { \
+ MOZ_ASSERT(NS_IsMainThread()); \
+ NS_LOG_RELEASE(this, 0, #_class); \
+ delete this; \
+ } \
+ NS_METHOD_(MozExternalRefCountType) Release(void) { \
+ MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
+ nsrefcnt count = --mRefCnt; \
+ if (count == 0) { \
+ if (NS_IsMainThread()) { \
+ DeleteToBeCalledOnMainThread(); \
+ } else { \
+ NS_DispatchToMainThread( \
+ new mozilla::layers::DeleteOnMainThreadTask<_class>(this)); \
+ } \
+ } else { \
+ NS_LOG_RELEASE(this, count, #_class); \
+ } \
+ return count; \
+ } \
+protected: \
+ ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
+private: \
+ ::mozilla::layers::HelperForMainThreadDestruction mHelperForMainThreadDestruction; \
+public:
+
+#endif