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