Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 : // IWYU pragma: private, include "nsISupports.h"
7 :
8 :
9 : #ifndef nsISupportsImpl_h__
10 : #define nsISupportsImpl_h__
11 :
12 : #include "nscore.h"
13 : #include "nsISupportsBase.h"
14 : #include "nsISupportsUtils.h"
15 :
16 : #if !defined(XPCOM_GLUE_AVOID_NSPR)
17 : #include "prthread.h" /* needed for cargo-culting headers */
18 : #endif
19 :
20 : #include "nsDebug.h"
21 : #include "nsXPCOM.h"
22 : #include <atomic>
23 : #include "mozilla/Attributes.h"
24 : #include "mozilla/Assertions.h"
25 : #include "mozilla/Compiler.h"
26 : #include "mozilla/Likely.h"
27 : #include "mozilla/MacroArgs.h"
28 : #include "mozilla/MacroForEach.h"
29 : #include "mozilla/TypeTraits.h"
30 :
31 : #define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X) \
32 : static_assert(!mozilla::IsDestructible<X>::value, \
33 : "Reference-counted class " #X " should not have a public destructor. " \
34 : "Make this class's destructor non-public");
35 :
36 : inline nsISupports*
37 6838 : ToSupports(nsISupports* aSupports)
38 : {
39 6838 : return aSupports;
40 : }
41 :
42 : inline nsISupports*
43 709 : ToCanonicalSupports(nsISupports* aSupports)
44 : {
45 709 : return nullptr;
46 : }
47 :
48 : ////////////////////////////////////////////////////////////////////////////////
49 : // Macros to help detect thread-safety:
50 :
51 : #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
52 :
53 : #include "prthread.h" /* needed for thread-safety checks */
54 :
55 : class nsAutoOwningThread
56 : {
57 : public:
58 : nsAutoOwningThread();
59 :
60 : // We move the actual assertion checks out-of-line to minimize code bloat,
61 : // but that means we have to pass a non-literal string to
62 : // MOZ_CRASH_UNSAFE_OOL. To make that more safe, the public interface
63 : // requires a literal string and passes that to the private interface; we
64 : // can then be assured that we effectively are passing a literal string
65 : // to MOZ_CRASH_UNSAFE_OOL.
66 : template<int N>
67 1304916 : void AssertOwnership(const char (&aMsg)[N]) const
68 : {
69 1304916 : AssertCurrentThreadOwnsMe(aMsg);
70 1304916 : }
71 :
72 : private:
73 : void AssertCurrentThreadOwnsMe(const char* aMsg) const;
74 :
75 : void* mThread;
76 : };
77 :
78 : #define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread;
79 : #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) \
80 : agg->_mOwningThread.AssertOwnership(#_class " not thread-safe")
81 : #define NS_ASSERT_OWNINGTHREAD(_class) NS_ASSERT_OWNINGTHREAD_AGGREGATE(this, _class)
82 : #else // !MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
83 :
84 : #define NS_DECL_OWNINGTHREAD /* nothing */
85 : #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) ((void)0)
86 : #define NS_ASSERT_OWNINGTHREAD(_class) ((void)0)
87 :
88 : #endif // MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
89 :
90 :
91 : // Macros for reference-count and constructor logging
92 :
93 : #if defined(NS_BUILD_REFCNT_LOGGING)
94 :
95 : #define NS_LOG_ADDREF(_p, _rc, _type, _size) \
96 : NS_LogAddRef((_p), (_rc), (_type), (uint32_t) (_size))
97 :
98 : #define NS_LOG_RELEASE(_p, _rc, _type) \
99 : NS_LogRelease((_p), (_rc), (_type))
100 :
101 : #include "mozilla/TypeTraits.h"
102 : #define MOZ_ASSERT_CLASSNAME(_type) \
103 : static_assert(mozilla::IsClass<_type>::value, \
104 : "Token '" #_type "' is not a class type.")
105 :
106 : #define MOZ_ASSERT_NOT_ISUPPORTS(_type) \
107 : static_assert(!mozilla::IsBaseOf<nsISupports, _type>::value, \
108 : "nsISupports classes don't need to call MOZ_COUNT_CTOR or MOZ_COUNT_DTOR");
109 :
110 : // Note that the following constructor/destructor logging macros are redundant
111 : // for refcounted objects that log via the NS_LOG_ADDREF/NS_LOG_RELEASE macros.
112 : // Refcount logging is preferred.
113 : #define MOZ_COUNT_CTOR(_type) \
114 : do { \
115 : MOZ_ASSERT_CLASSNAME(_type); \
116 : MOZ_ASSERT_NOT_ISUPPORTS(_type); \
117 : NS_LogCtor((void*)this, #_type, sizeof(*this)); \
118 : } while (0)
119 :
120 : #define MOZ_COUNT_CTOR_INHERITED(_type, _base) \
121 : do { \
122 : MOZ_ASSERT_CLASSNAME(_type); \
123 : MOZ_ASSERT_CLASSNAME(_base); \
124 : MOZ_ASSERT_NOT_ISUPPORTS(_type); \
125 : NS_LogCtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
126 : } while (0)
127 :
128 : #define MOZ_LOG_CTOR(_ptr, _name, _size) \
129 : do { \
130 : NS_LogCtor((void*)_ptr, _name, _size); \
131 : } while (0)
132 :
133 : #define MOZ_COUNT_DTOR(_type) \
134 : do { \
135 : MOZ_ASSERT_CLASSNAME(_type); \
136 : MOZ_ASSERT_NOT_ISUPPORTS(_type); \
137 : NS_LogDtor((void*)this, #_type, sizeof(*this)); \
138 : } while (0)
139 :
140 : #define MOZ_COUNT_DTOR_INHERITED(_type, _base) \
141 : do { \
142 : MOZ_ASSERT_CLASSNAME(_type); \
143 : MOZ_ASSERT_CLASSNAME(_base); \
144 : MOZ_ASSERT_NOT_ISUPPORTS(_type); \
145 : NS_LogDtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
146 : } while (0)
147 :
148 : #define MOZ_LOG_DTOR(_ptr, _name, _size) \
149 : do { \
150 : NS_LogDtor((void*)_ptr, _name, _size); \
151 : } while (0)
152 :
153 : /* nsCOMPtr.h allows these macros to be defined by clients
154 : * These logging functions require dynamic_cast<void*>, so they don't
155 : * do anything useful if we don't have dynamic_cast<void*>.
156 : * Note: The explicit comparison to nullptr is needed to avoid warnings
157 : * when _p is a nullptr itself. */
158 : #define NSCAP_LOG_ASSIGNMENT(_c, _p) \
159 : if (_p != nullptr) \
160 : NS_LogCOMPtrAddRef((_c),static_cast<nsISupports*>(_p))
161 :
162 : #define NSCAP_LOG_RELEASE(_c, _p) \
163 : if (_p) \
164 : NS_LogCOMPtrRelease((_c), static_cast<nsISupports*>(_p))
165 :
166 : #else /* !NS_BUILD_REFCNT_LOGGING */
167 :
168 : #define NS_LOG_ADDREF(_p, _rc, _type, _size)
169 : #define NS_LOG_RELEASE(_p, _rc, _type)
170 : #define MOZ_COUNT_CTOR(_type)
171 : #define MOZ_COUNT_CTOR_INHERITED(_type, _base)
172 : #define MOZ_LOG_CTOR(_ptr, _name, _size)
173 : #define MOZ_COUNT_DTOR(_type)
174 : #define MOZ_COUNT_DTOR_INHERITED(_type, _base)
175 : #define MOZ_LOG_DTOR(_ptr, _name, _size)
176 :
177 : #endif /* NS_BUILD_REFCNT_LOGGING */
178 :
179 :
180 : // Support for ISupports classes which interact with cycle collector.
181 :
182 : #define NS_NUMBER_OF_FLAGS_IN_REFCNT 2
183 : #define NS_IN_PURPLE_BUFFER (1 << 0)
184 : #define NS_IS_PURPLE (1 << 1)
185 : #define NS_REFCOUNT_CHANGE (1 << NS_NUMBER_OF_FLAGS_IN_REFCNT)
186 : #define NS_REFCOUNT_VALUE(_val) (_val >> NS_NUMBER_OF_FLAGS_IN_REFCNT)
187 :
188 : class nsCycleCollectingAutoRefCnt
189 : {
190 : public:
191 24809 : nsCycleCollectingAutoRefCnt() : mRefCntAndFlags(0) {}
192 :
193 : explicit nsCycleCollectingAutoRefCnt(uintptr_t aValue)
194 : : mRefCntAndFlags(aValue << NS_NUMBER_OF_FLAGS_IN_REFCNT)
195 : {
196 : }
197 :
198 : nsCycleCollectingAutoRefCnt(const nsCycleCollectingAutoRefCnt&) = delete;
199 : void operator=(const nsCycleCollectingAutoRefCnt&) = delete;
200 :
201 152875 : MOZ_ALWAYS_INLINE uintptr_t incr(nsISupports* aOwner)
202 : {
203 152875 : return incr(aOwner, nullptr);
204 : }
205 :
206 172708 : MOZ_ALWAYS_INLINE uintptr_t incr(void* aOwner,
207 : nsCycleCollectionParticipant* aCp)
208 : {
209 172708 : mRefCntAndFlags += NS_REFCOUNT_CHANGE;
210 172708 : mRefCntAndFlags &= ~NS_IS_PURPLE;
211 : // For incremental cycle collection, use the purple buffer to track objects
212 : // that have been AddRef'd.
213 172708 : if (!IsInPurpleBuffer()) {
214 24809 : mRefCntAndFlags |= NS_IN_PURPLE_BUFFER;
215 : // Refcount isn't zero, so Suspect won't delete anything.
216 24809 : MOZ_ASSERT(get() > 0);
217 24809 : NS_CycleCollectorSuspect3(aOwner, aCp, this, nullptr);
218 : }
219 172710 : return NS_REFCOUNT_VALUE(mRefCntAndFlags);
220 : }
221 :
222 1788 : MOZ_ALWAYS_INLINE void stabilizeForDeletion()
223 : {
224 : // Set refcnt to 1 and mark us to be in the purple buffer.
225 : // This way decr won't call suspect again.
226 1788 : mRefCntAndFlags = NS_REFCOUNT_CHANGE | NS_IN_PURPLE_BUFFER;
227 1788 : }
228 :
229 124132 : MOZ_ALWAYS_INLINE uintptr_t decr(nsISupports* aOwner,
230 : bool* aShouldDelete = nullptr)
231 : {
232 124132 : return decr(aOwner, nullptr, aShouldDelete);
233 : }
234 :
235 134459 : MOZ_ALWAYS_INLINE uintptr_t decr(void* aOwner,
236 : nsCycleCollectionParticipant* aCp,
237 : bool* aShouldDelete = nullptr)
238 : {
239 134459 : MOZ_ASSERT(get() > 0);
240 134459 : if (!IsInPurpleBuffer()) {
241 0 : mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
242 0 : mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
243 0 : uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags);
244 : // Suspect may delete 'aOwner' and 'this'!
245 0 : NS_CycleCollectorSuspect3(aOwner, aCp, this, aShouldDelete);
246 0 : return retval;
247 : }
248 134459 : mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
249 134459 : mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
250 134459 : return NS_REFCOUNT_VALUE(mRefCntAndFlags);
251 : }
252 :
253 0 : MOZ_ALWAYS_INLINE void RemovePurple()
254 : {
255 0 : MOZ_ASSERT(IsPurple(), "must be purple");
256 0 : mRefCntAndFlags &= ~NS_IS_PURPLE;
257 0 : }
258 :
259 1788 : MOZ_ALWAYS_INLINE void RemoveFromPurpleBuffer()
260 : {
261 1788 : MOZ_ASSERT(IsInPurpleBuffer());
262 1788 : mRefCntAndFlags &= ~(NS_IS_PURPLE | NS_IN_PURPLE_BUFFER);
263 1788 : }
264 :
265 0 : MOZ_ALWAYS_INLINE bool IsPurple() const
266 : {
267 0 : return !!(mRefCntAndFlags & NS_IS_PURPLE);
268 : }
269 :
270 310739 : MOZ_ALWAYS_INLINE bool IsInPurpleBuffer() const
271 : {
272 310739 : return !!(mRefCntAndFlags & NS_IN_PURPLE_BUFFER);
273 : }
274 :
275 504398 : MOZ_ALWAYS_INLINE nsrefcnt get() const
276 : {
277 504398 : return NS_REFCOUNT_VALUE(mRefCntAndFlags);
278 : }
279 :
280 317840 : MOZ_ALWAYS_INLINE operator nsrefcnt() const
281 : {
282 317840 : return get();
283 : }
284 :
285 : private:
286 : uintptr_t mRefCntAndFlags;
287 : };
288 :
289 : class nsAutoRefCnt
290 : {
291 : public:
292 45499 : nsAutoRefCnt() : mValue(0) {}
293 : explicit nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
294 :
295 : nsAutoRefCnt(const nsAutoRefCnt&) = delete;
296 : void operator=(const nsAutoRefCnt&) = delete;
297 :
298 : // only support prefix increment/decrement
299 516771 : nsrefcnt operator++() { return ++mValue; }
300 468933 : nsrefcnt operator--() { return --mValue; }
301 :
302 13286 : nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
303 1480243 : operator nsrefcnt() const { return mValue; }
304 0 : nsrefcnt get() const { return mValue; }
305 :
306 : static const bool isThreadSafe = false;
307 : private:
308 : nsrefcnt operator++(int) = delete;
309 : nsrefcnt operator--(int) = delete;
310 : nsrefcnt mValue;
311 : };
312 :
313 : namespace mozilla {
314 : class ThreadSafeAutoRefCnt
315 : {
316 : public:
317 23531 : ThreadSafeAutoRefCnt() : mValue(0) {}
318 3997 : explicit ThreadSafeAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
319 :
320 : ThreadSafeAutoRefCnt(const ThreadSafeAutoRefCnt&) = delete;
321 : void operator=(const ThreadSafeAutoRefCnt&) = delete;
322 :
323 : // only support prefix increment/decrement
324 285867 : MOZ_ALWAYS_INLINE nsrefcnt operator++()
325 : {
326 : // Memory synchronization is not required when incrementing a
327 : // reference count. The first increment of a reference count on a
328 : // thread is not important, since the first use of the object on a
329 : // thread can happen before it. What is important is the transfer
330 : // of the pointer to that thread, which may happen prior to the
331 : // first increment on that thread. The necessary memory
332 : // synchronization is done by the mechanism that transfers the
333 : // pointer between threads.
334 571734 : return mValue.fetch_add(1, std::memory_order_relaxed) + 1;
335 : }
336 260191 : MOZ_ALWAYS_INLINE nsrefcnt operator--()
337 : {
338 : // Since this may be the last release on this thread, we need
339 : // release semantics so that prior writes on this thread are visible
340 : // to the thread that destroys the object when it reads mValue with
341 : // acquire semantics.
342 520382 : nsrefcnt result = mValue.fetch_sub(1, std::memory_order_release) - 1;
343 260191 : if (result == 0) {
344 : // We're going to destroy the object on this thread, so we need
345 : // acquire semantics to synchronize with the memory released by
346 : // the last release on other threads, that is, to ensure that
347 : // writes prior to that release are now visible on this thread.
348 36637 : result = mValue.load(std::memory_order_acquire);
349 : }
350 260190 : return result;
351 : }
352 :
353 15956 : MOZ_ALWAYS_INLINE nsrefcnt operator=(nsrefcnt aValue)
354 : {
355 : // Use release semantics since we're not sure what the caller is
356 : // doing.
357 15956 : mValue.store(aValue, std::memory_order_release);
358 15956 : return aValue;
359 : }
360 480338 : MOZ_ALWAYS_INLINE operator nsrefcnt() const { return get(); }
361 480355 : MOZ_ALWAYS_INLINE nsrefcnt get() const
362 : {
363 : // Use acquire semantics since we're not sure what the caller is
364 : // doing.
365 960699 : return mValue.load(std::memory_order_acquire);
366 : }
367 :
368 : static const bool isThreadSafe = true;
369 : private:
370 : nsrefcnt operator++(int) = delete;
371 : nsrefcnt operator--(int) = delete;
372 : std::atomic<nsrefcnt> mValue;
373 : };
374 : } // namespace mozilla
375 :
376 : ///////////////////////////////////////////////////////////////////////////////
377 :
378 : /**
379 : * Declare the reference count variable and the implementations of the
380 : * AddRef and QueryInterface methods.
381 : */
382 :
383 : #define NS_DECL_ISUPPORTS \
384 : public: \
385 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
386 : void** aInstancePtr) override; \
387 : NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
388 : NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
389 : typedef mozilla::FalseType HasThreadSafeRefCnt; \
390 : protected: \
391 : nsAutoRefCnt mRefCnt; \
392 : NS_DECL_OWNINGTHREAD \
393 : public:
394 :
395 : #define NS_DECL_THREADSAFE_ISUPPORTS \
396 : public: \
397 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
398 : void** aInstancePtr) override; \
399 : NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
400 : NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
401 : typedef mozilla::TrueType HasThreadSafeRefCnt; \
402 : protected: \
403 : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
404 : NS_DECL_OWNINGTHREAD \
405 : public:
406 :
407 : #define NS_DECL_CYCLE_COLLECTING_ISUPPORTS \
408 : public: \
409 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
410 : void** aInstancePtr) override; \
411 : NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
412 : NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
413 : NS_IMETHOD_(void) DeleteCycleCollectable(void); \
414 : typedef mozilla::FalseType HasThreadSafeRefCnt; \
415 : protected: \
416 : nsCycleCollectingAutoRefCnt mRefCnt; \
417 : NS_DECL_OWNINGTHREAD \
418 : public:
419 :
420 :
421 : ///////////////////////////////////////////////////////////////////////////////
422 :
423 : /*
424 : * Implementation of AddRef and Release for non-nsISupports (ie "native")
425 : * cycle-collected classes that use the purple buffer to avoid leaks.
426 : */
427 :
428 : #define NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \
429 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
430 : MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
431 : NS_ASSERT_OWNINGTHREAD(_class); \
432 : nsrefcnt count = \
433 : mRefCnt.incr(static_cast<void*>(this), \
434 : _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
435 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
436 : return count;
437 :
438 : #define NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \
439 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
440 : NS_ASSERT_OWNINGTHREAD(_class); \
441 : nsrefcnt count = \
442 : mRefCnt.decr(static_cast<void*>(this), \
443 : _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
444 : NS_LOG_RELEASE(this, count, #_class); \
445 : return count;
446 :
447 : #define NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(_class) \
448 : NS_METHOD_(MozExternalRefCountType) _class::AddRef(void) \
449 : { \
450 : NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \
451 : }
452 :
453 : #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(_class, _last) \
454 : NS_METHOD_(MozExternalRefCountType) _class::Release(void) \
455 : { \
456 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
457 : NS_ASSERT_OWNINGTHREAD(_class); \
458 : bool shouldDelete = false; \
459 : nsrefcnt count = \
460 : mRefCnt.decr(static_cast<void*>(this), \
461 : _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant(), \
462 : &shouldDelete); \
463 : NS_LOG_RELEASE(this, count, #_class); \
464 : if (count == 0) { \
465 : mRefCnt.incr(static_cast<void*>(this), \
466 : _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
467 : _last; \
468 : mRefCnt.decr(static_cast<void*>(this), \
469 : _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
470 : if (shouldDelete) { \
471 : mRefCnt.stabilizeForDeletion(); \
472 : DeleteCycleCollectable(); \
473 : } \
474 : } \
475 : return count; \
476 : }
477 :
478 : #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(_class) \
479 : NS_METHOD_(MozExternalRefCountType) _class::Release(void) \
480 : { \
481 : NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \
482 : }
483 :
484 : #define NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(_class) \
485 : public: \
486 : NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
487 : NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \
488 : } \
489 : NS_METHOD_(MozExternalRefCountType) Release(void) { \
490 : NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \
491 : } \
492 : typedef mozilla::FalseType HasThreadSafeRefCnt; \
493 : protected: \
494 : nsCycleCollectingAutoRefCnt mRefCnt; \
495 : NS_DECL_OWNINGTHREAD \
496 : public:
497 :
498 :
499 : ///////////////////////////////////////////////////////////////////////////////
500 :
501 : /**
502 : * Use this macro to declare and implement the AddRef & Release methods for a
503 : * given non-XPCOM <i>_class</i>.
504 : *
505 : * @param _class The name of the class implementing the method
506 : * @param _destroy A statement that is executed when the object's
507 : * refcount drops to zero.
508 : * @param optional override Mark the AddRef & Release methods as overrides.
509 : */
510 : #define NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, _destroy, ...) \
511 : public: \
512 : NS_METHOD_(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
513 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
514 : MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
515 : NS_ASSERT_OWNINGTHREAD(_class); \
516 : ++mRefCnt; \
517 : NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
518 : return mRefCnt; \
519 : } \
520 : NS_METHOD_(MozExternalRefCountType) Release(void) __VA_ARGS__ { \
521 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
522 : NS_ASSERT_OWNINGTHREAD(_class); \
523 : --mRefCnt; \
524 : NS_LOG_RELEASE(this, mRefCnt, #_class); \
525 : if (mRefCnt == 0) { \
526 : mRefCnt = 1; /* stabilize */ \
527 : _destroy; \
528 : return 0; \
529 : } \
530 : return mRefCnt; \
531 : } \
532 : typedef mozilla::FalseType HasThreadSafeRefCnt; \
533 : protected: \
534 : nsAutoRefCnt mRefCnt; \
535 : NS_DECL_OWNINGTHREAD \
536 : public:
537 :
538 : /**
539 : * Use this macro to declare and implement the AddRef & Release methods for a
540 : * given non-XPCOM <i>_class</i>.
541 : *
542 : * @param _class The name of the class implementing the method
543 : * @param optional override Mark the AddRef & Release methods as overrides.
544 : */
545 : #define NS_INLINE_DECL_REFCOUNTING(_class, ...) \
546 : NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, delete(this), __VA_ARGS__)
547 :
548 : #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, ...) \
549 : public: \
550 : _decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
551 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
552 : MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
553 : nsrefcnt count = ++mRefCnt; \
554 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
555 : return (nsrefcnt) count; \
556 : } \
557 : _decl(MozExternalRefCountType) Release(void) __VA_ARGS__ { \
558 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
559 : nsrefcnt count = --mRefCnt; \
560 : NS_LOG_RELEASE(this, count, #_class); \
561 : if (count == 0) { \
562 : delete (this); \
563 : return 0; \
564 : } \
565 : return count; \
566 : } \
567 : typedef mozilla::TrueType HasThreadSafeRefCnt; \
568 : protected: \
569 : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
570 : public:
571 :
572 : /**
573 : * Use this macro to declare and implement the AddRef & Release methods for a
574 : * given non-XPCOM <i>_class</i> in a threadsafe manner.
575 : *
576 : * DOES NOT DO REFCOUNT STABILIZATION!
577 : *
578 : * @param _class The name of the class implementing the method
579 : */
580 : #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class, ...) \
581 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_METHOD_, __VA_ARGS__)
582 :
583 : /**
584 : * Like NS_INLINE_DECL_THREADSAFE_REFCOUNTING with AddRef & Release declared
585 : * virtual.
586 : */
587 : #define NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(_class, ...) \
588 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_IMETHOD_, __VA_ARGS__)
589 :
590 : /**
591 : * Use this macro in interface classes that you want to be able to reference
592 : * using RefPtr, but don't want to provide a refcounting implemenation. The
593 : * refcounting implementation can be provided by concrete subclasses that
594 : * implement the interface.
595 : */
596 : #define NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING \
597 : public: \
598 : NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; \
599 : NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; \
600 : public:
601 :
602 : /**
603 : * Use this macro to implement the AddRef method for a given <i>_class</i>
604 : * @param _class The name of the class implementing the method
605 : */
606 : #define NS_IMPL_ADDREF(_class) \
607 : NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \
608 : { \
609 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
610 : MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
611 : if (!mRefCnt.isThreadSafe) \
612 : NS_ASSERT_OWNINGTHREAD(_class); \
613 : nsrefcnt count = ++mRefCnt; \
614 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
615 : return count; \
616 : }
617 :
618 : /**
619 : * Use this macro to implement the AddRef method for a given <i>_class</i>
620 : * implemented as a wholly owned aggregated object intended to implement
621 : * interface(s) for its owner
622 : * @param _class The name of the class implementing the method
623 : * @param _aggregator the owning/containing object
624 : */
625 : #define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \
626 : NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \
627 : { \
628 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
629 : NS_PRECONDITION(_aggregator, "null aggregator"); \
630 : return (_aggregator)->AddRef(); \
631 : }
632 :
633 : /**
634 : * Use this macro to implement the Release method for a given
635 : * <i>_class</i>.
636 : * @param _class The name of the class implementing the method
637 : * @param _destroy A statement that is executed when the object's
638 : * refcount drops to zero.
639 : *
640 : * For example,
641 : *
642 : * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
643 : *
644 : * will cause
645 : *
646 : * Destroy(this);
647 : *
648 : * to be invoked when the object's refcount drops to zero. This
649 : * allows for arbitrary teardown activity to occur (e.g., deallocation
650 : * of object allocated with placement new).
651 : */
652 : #define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
653 : NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
654 : { \
655 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
656 : if (!mRefCnt.isThreadSafe) \
657 : NS_ASSERT_OWNINGTHREAD(_class); \
658 : nsrefcnt count = --mRefCnt; \
659 : NS_LOG_RELEASE(this, count, #_class); \
660 : if (count == 0) { \
661 : mRefCnt = 1; /* stabilize */ \
662 : _destroy; \
663 : return 0; \
664 : } \
665 : return count; \
666 : }
667 :
668 : /**
669 : * Use this macro to implement the Release method for a given <i>_class</i>
670 : * @param _class The name of the class implementing the method
671 : *
672 : * A note on the 'stabilization' of the refcnt to one. At that point,
673 : * the object's refcount will have gone to zero. The object's
674 : * destructor may trigger code that attempts to QueryInterface() and
675 : * Release() 'this' again. Doing so will temporarily increment and
676 : * decrement the refcount. (Only a logic error would make one try to
677 : * keep a permanent hold on 'this'.) To prevent re-entering the
678 : * destructor, we make sure that no balanced refcounting can return
679 : * the refcount to |0|.
680 : */
681 : #define NS_IMPL_RELEASE(_class) \
682 : NS_IMPL_RELEASE_WITH_DESTROY(_class, delete (this))
683 :
684 : /**
685 : * Use this macro to implement the Release method for a given <i>_class</i>
686 : * implemented as a wholly owned aggregated object intended to implement
687 : * interface(s) for its owner
688 : * @param _class The name of the class implementing the method
689 : * @param _aggregator the owning/containing object
690 : */
691 : #define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \
692 : NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
693 : { \
694 : NS_PRECONDITION(_aggregator, "null aggregator"); \
695 : return (_aggregator)->Release(); \
696 : }
697 :
698 :
699 : #define NS_IMPL_CYCLE_COLLECTING_ADDREF(_class) \
700 : NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \
701 : { \
702 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
703 : MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
704 : NS_ASSERT_OWNINGTHREAD(_class); \
705 : nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
706 : nsrefcnt count = mRefCnt.incr(base); \
707 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
708 : return count; \
709 : }
710 :
711 : #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy) \
712 : NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
713 : { \
714 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
715 : NS_ASSERT_OWNINGTHREAD(_class); \
716 : nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
717 : nsrefcnt count = mRefCnt.decr(base); \
718 : NS_LOG_RELEASE(this, count, #_class); \
719 : return count; \
720 : } \
721 : NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void) \
722 : { \
723 : _destroy; \
724 : }
725 :
726 : #define NS_IMPL_CYCLE_COLLECTING_RELEASE(_class) \
727 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, delete (this))
728 :
729 : // _LAST_RELEASE can be useful when certain resources should be released
730 : // as soon as we know the object will be deleted.
731 : #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last) \
732 : NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
733 : { \
734 : MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
735 : NS_ASSERT_OWNINGTHREAD(_class); \
736 : bool shouldDelete = false; \
737 : nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
738 : nsrefcnt count = mRefCnt.decr(base, &shouldDelete); \
739 : NS_LOG_RELEASE(this, count, #_class); \
740 : if (count == 0) { \
741 : mRefCnt.incr(base); \
742 : _last; \
743 : mRefCnt.decr(base); \
744 : if (shouldDelete) { \
745 : mRefCnt.stabilizeForDeletion(); \
746 : DeleteCycleCollectable(); \
747 : } \
748 : } \
749 : return count; \
750 : } \
751 : NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void) \
752 : { \
753 : delete this; \
754 : }
755 :
756 : ///////////////////////////////////////////////////////////////////////////////
757 :
758 : /**
759 : * There are two ways of implementing QueryInterface, and we use both:
760 : *
761 : * Table-driven QueryInterface uses a static table of IID->offset mappings
762 : * and a shared helper function. Using it tends to reduce codesize and improve
763 : * runtime performance (due to processor cache hits).
764 : *
765 : * Macro-driven QueryInterface generates a QueryInterface function directly
766 : * using common macros. This is necessary if special QueryInterface features
767 : * are being used (such as tearoffs and conditional interfaces).
768 : *
769 : * These methods can be combined into a table-driven function call followed
770 : * by custom code for tearoffs and conditionals.
771 : */
772 :
773 : struct QITableEntry
774 : {
775 : const nsIID* iid; // null indicates end of the QITableEntry array
776 : int32_t offset;
777 : };
778 :
779 : nsresult NS_FASTCALL
780 : NS_TableDrivenQI(void* aThis, REFNSIID aIID,
781 : void** aInstancePtr, const QITableEntry* aEntries);
782 :
783 : /**
784 : * Implement table-driven queryinterface
785 : */
786 :
787 : #define NS_INTERFACE_TABLE_HEAD(_class) \
788 : NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
789 : { \
790 : NS_ASSERTION(aInstancePtr, \
791 : "QueryInterface requires a non-NULL destination!"); \
792 : nsresult rv = NS_ERROR_FAILURE;
793 :
794 : #define NS_INTERFACE_TABLE_BEGIN \
795 : static const QITableEntry table[] = {
796 :
797 : #define NS_INTERFACE_TABLE_ENTRY(_class, _interface) \
798 : { &NS_GET_IID(_interface), \
799 : int32_t(reinterpret_cast<char*>( \
800 : static_cast<_interface*>((_class*) 0x1000)) - \
801 : reinterpret_cast<char*>((_class*) 0x1000)) \
802 : },
803 :
804 : #define NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, _interface, _implClass) \
805 : { &NS_GET_IID(_interface), \
806 : int32_t(reinterpret_cast<char*>( \
807 : static_cast<_interface*>( \
808 : static_cast<_implClass*>( \
809 : (_class*) 0x1000))) - \
810 : reinterpret_cast<char*>((_class*) 0x1000)) \
811 : },
812 :
813 : /*
814 : * XXX: we want to use mozilla::ArrayLength (or equivalent,
815 : * MOZ_ARRAY_LENGTH) in this condition, but some versions of GCC don't
816 : * see that the static_assert condition is actually constant in those
817 : * cases, even with constexpr support (?).
818 : */
819 : #define NS_INTERFACE_TABLE_END_WITH_PTR(_ptr) \
820 : { nullptr, 0 } }; \
821 : static_assert((sizeof(table)/sizeof(table[0])) > 1, "need at least 1 interface"); \
822 : rv = NS_TableDrivenQI(static_cast<void*>(_ptr), \
823 : aIID, aInstancePtr, table);
824 :
825 : #define NS_INTERFACE_TABLE_END \
826 : NS_INTERFACE_TABLE_END_WITH_PTR(this)
827 :
828 : #define NS_INTERFACE_TABLE_TAIL \
829 : return rv; \
830 : }
831 :
832 : #define NS_INTERFACE_TABLE_TAIL_INHERITING(_baseclass) \
833 : if (NS_SUCCEEDED(rv)) \
834 : return rv; \
835 : return _baseclass::QueryInterface(aIID, aInstancePtr); \
836 : }
837 :
838 : #define NS_INTERFACE_TABLE_TAIL_USING_AGGREGATOR(_aggregator) \
839 : if (NS_SUCCEEDED(rv)) \
840 : return rv; \
841 : NS_ASSERTION(_aggregator, "null aggregator"); \
842 : return _aggregator->QueryInterface(aIID, aInstancePtr) \
843 : }
844 :
845 : /**
846 : * This implements query interface with two assumptions: First, the
847 : * class in question implements nsISupports and its own interface and
848 : * nothing else. Second, the implementation of the class's primary
849 : * inheritance chain leads to its own interface.
850 : *
851 : * @param _class The name of the class implementing the method
852 : * @param _classiiddef The name of the #define symbol that defines the IID
853 : * for the class (e.g. NS_ISUPPORTS_IID)
854 : */
855 :
856 : #define NS_IMPL_QUERY_HEAD(_class) \
857 : NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
858 : { \
859 : NS_ASSERTION(aInstancePtr, \
860 : "QueryInterface requires a non-NULL destination!"); \
861 : nsISupports* foundInterface;
862 :
863 : #define NS_IMPL_QUERY_BODY(_interface) \
864 : if ( aIID.Equals(NS_GET_IID(_interface)) ) \
865 : foundInterface = static_cast<_interface*>(this); \
866 : else
867 :
868 : #define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \
869 : if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \
870 : foundInterface = static_cast<_interface*>(this); \
871 : else
872 :
873 : #define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \
874 : if ( aIID.Equals(NS_GET_IID(_interface)) ) \
875 : foundInterface = static_cast<_interface*>( \
876 : static_cast<_implClass*>(this)); \
877 : else
878 :
879 : #define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \
880 : if ( aIID.Equals(NS_GET_IID(_interface)) ) \
881 : foundInterface = static_cast<_interface*>(_aggregate); \
882 : else
883 :
884 : #define NS_IMPL_QUERY_TAIL_GUTS \
885 : foundInterface = 0; \
886 : nsresult status; \
887 : if ( !foundInterface ) \
888 : { \
889 : /* nsISupports should be handled by this point. If not, fail. */ \
890 : MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsISupports))); \
891 : status = NS_NOINTERFACE; \
892 : } \
893 : else \
894 : { \
895 : NS_ADDREF(foundInterface); \
896 : status = NS_OK; \
897 : } \
898 : *aInstancePtr = foundInterface; \
899 : return status; \
900 : }
901 :
902 : #define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \
903 : foundInterface = 0; \
904 : nsresult status; \
905 : if ( !foundInterface ) \
906 : status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \
907 : else \
908 : { \
909 : NS_ADDREF(foundInterface); \
910 : status = NS_OK; \
911 : } \
912 : *aInstancePtr = foundInterface; \
913 : return status; \
914 : }
915 :
916 : #define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \
917 : foundInterface = 0; \
918 : nsresult status; \
919 : if ( !foundInterface ) { \
920 : NS_ASSERTION(_aggregator, "null aggregator"); \
921 : status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \
922 : } else \
923 : { \
924 : NS_ADDREF(foundInterface); \
925 : status = NS_OK; \
926 : } \
927 : *aInstancePtr = foundInterface; \
928 : return status; \
929 : }
930 :
931 : #define NS_IMPL_QUERY_TAIL(_supports_interface) \
932 : NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \
933 : NS_IMPL_QUERY_TAIL_GUTS
934 :
935 :
936 : /*
937 : This is the new scheme. Using this notation now will allow us to switch to
938 : a table driven mechanism when it's ready. Note the difference between this
939 : and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must
940 : explicitly mention |nsISupports| when using the interface maps.
941 : */
942 : #define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass)
943 : #define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface)
944 : #define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \
945 : NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
946 : #define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \
947 : NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
948 :
949 : #define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS
950 : #define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \
951 : NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
952 : #define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \
953 : NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
954 : #define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \
955 : NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
956 :
957 : #define NS_INTERFACE_TABLE0(_class) \
958 : NS_INTERFACE_TABLE_BEGIN \
959 : NS_INTERFACE_TABLE_ENTRY(_class, nsISupports) \
960 : NS_INTERFACE_TABLE_END
961 :
962 : #define NS_INTERFACE_TABLE(aClass, ...) \
963 : static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0, \
964 : "Need more arguments to NS_INTERFACE_TABLE"); \
965 : NS_INTERFACE_TABLE_BEGIN \
966 : MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
967 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(aClass, nsISupports, \
968 : MOZ_ARG_1(__VA_ARGS__)) \
969 : NS_INTERFACE_TABLE_END
970 :
971 : #define NS_IMPL_QUERY_INTERFACE0(_class) \
972 : NS_INTERFACE_TABLE_HEAD(_class) \
973 : NS_INTERFACE_TABLE0(_class) \
974 : NS_INTERFACE_TABLE_TAIL
975 :
976 : #define NS_IMPL_QUERY_INTERFACE(aClass, ...) \
977 : NS_INTERFACE_TABLE_HEAD(aClass) \
978 : NS_INTERFACE_TABLE(aClass, __VA_ARGS__) \
979 : NS_INTERFACE_TABLE_TAIL
980 :
981 : /**
982 : * Declare that you're going to inherit from something that already
983 : * implements nsISupports, but also implements an additional interface, thus
984 : * causing an ambiguity. In this case you don't need another mRefCnt, you
985 : * just need to forward the definitions to the appropriate superclass. E.g.
986 : *
987 : * class Bar : public Foo, public nsIBar { // both provide nsISupports
988 : * public:
989 : * NS_DECL_ISUPPORTS_INHERITED
990 : * ...other nsIBar and Bar methods...
991 : * };
992 : */
993 : #define NS_DECL_ISUPPORTS_INHERITED \
994 : public: \
995 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
996 : void** aInstancePtr) override; \
997 : NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
998 : NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
999 :
1000 : /**
1001 : * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
1002 : * to implement the nsISupports methods, forwarding the invocations to a
1003 : * superclass that already implements nsISupports.
1004 : *
1005 : * Note that I didn't make these inlined because they're virtual methods.
1006 : */
1007 :
1008 : #define NS_IMPL_ADDREF_INHERITED(Class, Super) \
1009 : NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void) \
1010 : { \
1011 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class) \
1012 : nsrefcnt r = Super::AddRef(); \
1013 : NS_LOG_ADDREF(this, r, #Class, sizeof(*this)); \
1014 : return r; \
1015 : }
1016 :
1017 : #define NS_IMPL_RELEASE_INHERITED(Class, Super) \
1018 : NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
1019 : { \
1020 : nsrefcnt r = Super::Release(); \
1021 : NS_LOG_RELEASE(this, r, #Class); \
1022 : return r; \
1023 : }
1024 :
1025 : /**
1026 : * As above but not logging the addref/release; needed if the base
1027 : * class might be aggregated.
1028 : */
1029 : #define NS_IMPL_NONLOGGING_ADDREF_INHERITED(Class, Super) \
1030 : NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void) \
1031 : { \
1032 : MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class) \
1033 : return Super::AddRef(); \
1034 : }
1035 :
1036 : #define NS_IMPL_NONLOGGING_RELEASE_INHERITED(Class, Super) \
1037 : NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
1038 : { \
1039 : return Super::Release(); \
1040 : }
1041 :
1042 : #define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */
1043 :
1044 : #define NS_INTERFACE_TABLE_INHERITED(aClass, ...) \
1045 : static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0, \
1046 : "Need more arguments to NS_INTERFACE_TABLE_INHERITED"); \
1047 : NS_INTERFACE_TABLE_BEGIN \
1048 : MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
1049 : NS_INTERFACE_TABLE_END
1050 :
1051 : #define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...) \
1052 : NS_INTERFACE_TABLE_HEAD(aClass) \
1053 : NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \
1054 : NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
1055 :
1056 : /**
1057 : * Convenience macros for implementing all nsISupports methods for
1058 : * a simple class.
1059 : * @param _class The name of the class implementing the method
1060 : * @param _classiiddef The name of the #define symbol that defines the IID
1061 : * for the class (e.g. NS_ISUPPORTS_IID)
1062 : */
1063 :
1064 : #define NS_IMPL_ISUPPORTS0(_class) \
1065 : NS_IMPL_ADDREF(_class) \
1066 : NS_IMPL_RELEASE(_class) \
1067 : NS_IMPL_QUERY_INTERFACE0(_class)
1068 :
1069 : #define NS_IMPL_ISUPPORTS(aClass, ...) \
1070 : NS_IMPL_ADDREF(aClass) \
1071 : NS_IMPL_RELEASE(aClass) \
1072 : NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__)
1073 :
1074 : #define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper) \
1075 : NS_INTERFACE_TABLE_HEAD(aClass) \
1076 : NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper) \
1077 : NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
1078 : NS_IMPL_RELEASE_INHERITED(aClass, aSuper) \
1079 :
1080 : #define NS_IMPL_ISUPPORTS_INHERITED(aClass, aSuper, ...) \
1081 : NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, __VA_ARGS__) \
1082 : NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
1083 : NS_IMPL_RELEASE_INHERITED(aClass, aSuper)
1084 :
1085 : /*
1086 : * Macro to glue together a QI that starts with an interface table
1087 : * and segues into an interface map (e.g. it uses singleton classinfo
1088 : * or tearoffs).
1089 : */
1090 : #define NS_INTERFACE_TABLE_TO_MAP_SEGUE \
1091 : if (rv == NS_OK) return rv; \
1092 : nsISupports* foundInterface;
1093 :
1094 :
1095 : ///////////////////////////////////////////////////////////////////////////////
1096 : /**
1097 : *
1098 : * Threadsafe implementations of the ISupports convenience macros.
1099 : *
1100 : * @note These are not available when linking against the standalone glue,
1101 : * because the implementation requires PR_ symbols.
1102 : */
1103 : #define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
1104 :
1105 : /**
1106 : * Macro to generate nsIClassInfo methods for classes which do not have
1107 : * corresponding nsIFactory implementations.
1108 : */
1109 : #define NS_IMPL_THREADSAFE_CI(_class) \
1110 : NS_IMETHODIMP \
1111 : _class::GetInterfaces(uint32_t* _count, nsIID*** _array) \
1112 : { \
1113 : return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \
1114 : } \
1115 : \
1116 : NS_IMETHODIMP \
1117 : _class::GetScriptableHelper(nsIXPCScriptable** _retval) \
1118 : { \
1119 : *_retval = nullptr; \
1120 : return NS_OK; \
1121 : } \
1122 : \
1123 : NS_IMETHODIMP \
1124 : _class::GetContractID(char** _contractID) \
1125 : { \
1126 : *_contractID = nullptr; \
1127 : return NS_OK; \
1128 : } \
1129 : \
1130 : NS_IMETHODIMP \
1131 : _class::GetClassDescription(char** _classDescription) \
1132 : { \
1133 : *_classDescription = nullptr; \
1134 : return NS_OK; \
1135 : } \
1136 : \
1137 : NS_IMETHODIMP \
1138 : _class::GetClassID(nsCID** _classID) \
1139 : { \
1140 : *_classID = nullptr; \
1141 : return NS_OK; \
1142 : } \
1143 : \
1144 : NS_IMETHODIMP \
1145 : _class::GetFlags(uint32_t* _flags) \
1146 : { \
1147 : *_flags = nsIClassInfo::THREADSAFE; \
1148 : return NS_OK; \
1149 : } \
1150 : \
1151 : NS_IMETHODIMP \
1152 : _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
1153 : { \
1154 : return NS_ERROR_NOT_AVAILABLE; \
1155 : }
1156 :
1157 : #endif
|