Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #ifndef THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
6 : #define THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
7 :
8 : #include "base/message_loop.h"
9 : #include "MainThreadUtils.h"
10 : #include "nsThreadUtils.h"
11 :
12 : namespace mozilla {
13 : namespace layers {
14 :
15 1 : inline MessageLoop* GetMainLoopAssertingMainThread()
16 : {
17 1 : MOZ_ASSERT(NS_IsMainThread());
18 1 : return MessageLoop::current();
19 : }
20 :
21 1 : inline MessageLoop* GetMainLoop()
22 : {
23 1 : static MessageLoop* sMainLoop = GetMainLoopAssertingMainThread();
24 1 : return sMainLoop;
25 : }
26 :
27 : struct HelperForMainThreadDestruction
28 : {
29 1 : HelperForMainThreadDestruction()
30 : {
31 1 : MOZ_ASSERT(NS_IsMainThread());
32 1 : GetMainLoop();
33 1 : }
34 :
35 0 : ~HelperForMainThreadDestruction()
36 : {
37 0 : MOZ_ASSERT(NS_IsMainThread());
38 0 : }
39 : };
40 :
41 : template<typename T>
42 0 : struct DeleteOnMainThreadTask : public Runnable
43 : {
44 : T* mToDelete;
45 0 : explicit DeleteOnMainThreadTask(T* aToDelete)
46 : : Runnable("layers::DeleteOnMainThreadTask")
47 0 : , mToDelete(aToDelete)
48 : {
49 0 : }
50 0 : NS_IMETHOD Run() override {
51 0 : MOZ_ASSERT(NS_IsMainThread());
52 0 : mToDelete->DeleteToBeCalledOnMainThread();
53 0 : return NS_OK;
54 : }
55 : };
56 :
57 : } // namespace layers
58 : } // namespace mozilla
59 :
60 : #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(_class) \
61 : public: \
62 : NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
63 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
64 : MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
65 : nsrefcnt count = ++mRefCnt; \
66 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
67 : return (nsrefcnt) count; \
68 : } \
69 : void DeleteToBeCalledOnMainThread() { \
70 : MOZ_ASSERT(NS_IsMainThread()); \
71 : NS_LOG_RELEASE(this, 0, #_class); \
72 : delete this; \
73 : } \
74 : NS_METHOD_(MozExternalRefCountType) Release(void) { \
75 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
76 : nsrefcnt count = --mRefCnt; \
77 : if (count == 0) { \
78 : if (NS_IsMainThread()) { \
79 : DeleteToBeCalledOnMainThread(); \
80 : } else { \
81 : NS_DispatchToMainThread( \
82 : new mozilla::layers::DeleteOnMainThreadTask<_class>(this)); \
83 : } \
84 : } else { \
85 : NS_LOG_RELEASE(this, count, #_class); \
86 : } \
87 : return count; \
88 : } \
89 : protected: \
90 : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
91 : private: \
92 : ::mozilla::layers::HelperForMainThreadDestruction mHelperForMainThreadDestruction; \
93 : public:
94 :
95 : #endif
|