1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is XPCOM.
16 : *
17 : * The Initial Developer of the Original Code is Netscape Communications Corp.
18 : * Portions created by the Initial Developer are Copyright (C) 2001
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPL"), or
25 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 :
38 : #ifndef nsISupportsImpl_h__
39 : #define nsISupportsImpl_h__
40 :
41 : #ifndef nscore_h___
42 : #include "nscore.h"
43 : #endif
44 :
45 : #ifndef nsISupportsBase_h__
46 : #include "nsISupportsBase.h"
47 : #endif
48 :
49 : #ifndef nsISupportsUtils_h__
50 : #include "nsISupportsUtils.h"
51 : #endif
52 :
53 :
54 : #if !defined(XPCOM_GLUE_AVOID_NSPR)
55 : #include "prthread.h" /* needed for thread-safety checks */
56 : #include "nsAtomicRefcnt.h" /* for NS_Atomic{Increment,Decrement}Refcnt */
57 : #endif
58 :
59 : #include "nsDebug.h"
60 : #include "nsTraceRefcnt.h"
61 : #include "nsCycleCollector.h"
62 : #include "nsCycleCollectorUtils.h"
63 :
64 : ////////////////////////////////////////////////////////////////////////////////
65 : // Macros to help detect thread-safety:
66 :
67 : #if defined(NS_DEBUG) && !defined(XPCOM_GLUE_AVOID_NSPR)
68 :
69 : class nsAutoOwningThread {
70 : public:
71 0 : nsAutoOwningThread() { mThread = PR_GetCurrentThread(); }
72 0 : void *GetThread() const { return mThread; }
73 :
74 : private:
75 : void *mThread;
76 : };
77 :
78 : #define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread;
79 : #define NS_ASSERT_OWNINGTHREAD(_class) \
80 : NS_CheckThreadSafe(_mOwningThread.GetThread(), #_class " not thread-safe")
81 : #define NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class) \
82 : do { \
83 : if (NS_IsCycleCollectorThread()) { \
84 : NS_ERROR("Changing refcount of " #_class " object during Traverse is " \
85 : "not permitted!"); \
86 : } \
87 : else { \
88 : NS_ASSERT_OWNINGTHREAD(_class); \
89 : } \
90 : } while (0)
91 :
92 : #else // !NS_DEBUG
93 :
94 : #define NS_DECL_OWNINGTHREAD /* nothing */
95 : #define NS_ASSERT_OWNINGTHREAD(_class) ((void)0)
96 : #define NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class) ((void)0)
97 :
98 : #endif // NS_DEBUG
99 :
100 : #define NS_CCAR_REFCNT_BIT 1
101 : #define NS_CCAR_REFCNT_TO_TAGGED(rc_) \
102 : NS_INT32_TO_PTR((rc_ << 1) | NS_CCAR_REFCNT_BIT)
103 : #define NS_CCAR_PURPLE_ENTRY_TO_TAGGED(pe_) \
104 : static_cast<void*>(pe_)
105 : #define NS_CCAR_TAGGED_TO_REFCNT(tagged_) \
106 : nsrefcnt(NS_PTR_TO_INT32(tagged_) >> 1)
107 : #define NS_CCAR_TAGGED_TO_PURPLE_ENTRY(tagged_) \
108 : static_cast<nsPurpleBufferEntry*>(tagged_)
109 : #define NS_CCAR_TAGGED_STABILIZED_REFCNT NS_CCAR_PURPLE_ENTRY_TO_TAGGED(0)
110 :
111 : // Support for ISupports classes which interact with cycle collector.
112 :
113 : /**
114 : * This struct (once shipped) will be FROZEN with respect to the
115 : * NS_CycleCollectorSuspect2 and NS_CycleCollectorForget2 functions. If
116 : * we need to change the struct, we'll need Suspect3 and Forget3 for the
117 : * new versions.
118 : */
119 : struct nsPurpleBufferEntry {
120 : union {
121 : nsISupports *mObject; // when low bit unset
122 : nsPurpleBufferEntry *mNextInFreeList; // when low bit set
123 : };
124 : // When an object is in the purple buffer, it replaces its reference
125 : // count with a (tagged) pointer to this entry, so we store the
126 : // reference count for it.
127 : nsrefcnt mRefCnt;
128 : };
129 :
130 : class nsCycleCollectingAutoRefCnt {
131 :
132 : public:
133 : nsCycleCollectingAutoRefCnt()
134 : : mTagged(NS_CCAR_REFCNT_TO_TAGGED(0))
135 : {}
136 :
137 : nsCycleCollectingAutoRefCnt(nsrefcnt aValue)
138 : : mTagged(NS_CCAR_REFCNT_TO_TAGGED(aValue))
139 : {
140 : }
141 :
142 : nsrefcnt incr(nsISupports *owner)
143 : {
144 : if (NS_UNLIKELY(mTagged == NS_CCAR_TAGGED_STABILIZED_REFCNT)) {
145 : // The sentinel value "purple bit alone, refcount 0" means
146 : // that we're stabilized, during finalization. In this
147 : // state we lie about our actual refcount if anyone asks
148 : // and say it's 2, which is basically true: the caller who
149 : // is incrementing has a reference, as does the decr() frame
150 : // that stabilized-and-is-deleting us.
151 : return 2;
152 : }
153 :
154 : nsrefcnt refcount;
155 : if (IsPurple()) {
156 : nsPurpleBufferEntry *e = NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged);
157 : NS_ASSERTION(e->mObject == owner, "wrong entry");
158 : refcount = e->mRefCnt;
159 : NS_ASSERTION(refcount != 0, "purple ISupports pointer with zero refcnt");
160 :
161 : if (NS_LIKELY(NS_CycleCollectorForget2(e))) {
162 : // |e| is now invalid
163 : ++refcount;
164 : mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
165 : } else {
166 : ++refcount;
167 : e->mRefCnt = refcount;
168 : }
169 : } else {
170 : refcount = NS_CCAR_TAGGED_TO_REFCNT(mTagged);
171 : ++refcount;
172 : mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
173 : }
174 :
175 : return refcount;
176 : }
177 :
178 : void stabilizeForDeletion(nsISupports*)
179 : {
180 : mTagged = NS_CCAR_TAGGED_STABILIZED_REFCNT;
181 : }
182 :
183 : nsrefcnt decr(nsISupports *owner)
184 : {
185 : if (NS_UNLIKELY(mTagged == NS_CCAR_TAGGED_STABILIZED_REFCNT))
186 : return 1;
187 :
188 : nsrefcnt refcount;
189 : if (IsPurple()) {
190 : nsPurpleBufferEntry *e = NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged);
191 : NS_ASSERTION(e->mObject == owner, "wrong entry");
192 : refcount = e->mRefCnt;
193 : --refcount;
194 :
195 : if (NS_UNLIKELY(refcount == 0)) {
196 : if (NS_UNLIKELY(!NS_CycleCollectorForget2(e))) {
197 : NS_NOTREACHED("forget should not fail when reference count hits 0");
198 : // Clear the entry's pointer to us.
199 : e->mObject = nsnull;
200 : }
201 : mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
202 : } else {
203 : e->mRefCnt = refcount;
204 : }
205 : } else {
206 : refcount = NS_CCAR_TAGGED_TO_REFCNT(mTagged);
207 : --refcount;
208 :
209 : nsPurpleBufferEntry *e;
210 : if (NS_LIKELY(refcount > 0) &&
211 : ((e = NS_CycleCollectorSuspect2(owner)))) {
212 : e->mRefCnt = refcount;
213 : mTagged = NS_CCAR_PURPLE_ENTRY_TO_TAGGED(e);
214 : } else {
215 : mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
216 : }
217 : }
218 :
219 : return refcount;
220 : }
221 :
222 : void unmarkPurple()
223 : {
224 : NS_ASSERTION(IsPurple(), "must be purple");
225 : nsrefcnt refcount = NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mRefCnt;
226 : mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
227 : }
228 :
229 : void RemovePurple()
230 : {
231 : NS_ASSERTION(IsPurple(), "must be purple");
232 : #ifdef DEBUG_CC
233 : nsCycleCollector_logPurpleRemoval(
234 : NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject);
235 : #endif
236 : // The entry will be added to the free list later.
237 : NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject = nsnull;
238 : unmarkPurple();
239 : }
240 :
241 : bool IsPurple() const
242 : {
243 : NS_ASSERTION(mTagged != NS_CCAR_TAGGED_STABILIZED_REFCNT,
244 : "should have checked for stabilization first");
245 : return !(NS_PTR_TO_INT32(mTagged) & NS_CCAR_REFCNT_BIT);
246 : }
247 :
248 : nsrefcnt get() const
249 : {
250 : if (NS_UNLIKELY(mTagged == NS_CCAR_TAGGED_STABILIZED_REFCNT))
251 : return 1;
252 :
253 : return NS_UNLIKELY(IsPurple())
254 : ? NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mRefCnt
255 : : NS_CCAR_TAGGED_TO_REFCNT(mTagged);
256 : }
257 :
258 : operator nsrefcnt() const
259 : {
260 : return get();
261 : }
262 :
263 : private:
264 : void *mTagged;
265 : };
266 :
267 : class nsAutoRefCnt {
268 :
269 : public:
270 0 : nsAutoRefCnt() : mValue(0) {}
271 : nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
272 :
273 : // only support prefix increment/decrement
274 0 : nsrefcnt operator++() { return ++mValue; }
275 0 : nsrefcnt operator--() { return --mValue; }
276 :
277 0 : nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
278 0 : operator nsrefcnt() const { return mValue; }
279 : nsrefcnt get() const { return mValue; }
280 : private:
281 : // do not define these to enforce the faster prefix notation
282 : nsrefcnt operator++(int);
283 : nsrefcnt operator--(int);
284 : nsrefcnt mValue;
285 : };
286 :
287 : ///////////////////////////////////////////////////////////////////////////////
288 :
289 : /**
290 : * Declare the reference count variable and the implementations of the
291 : * AddRef and QueryInterface methods.
292 : */
293 :
294 : #define NS_DECL_ISUPPORTS \
295 : public: \
296 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
297 : void** aInstancePtr); \
298 : NS_IMETHOD_(nsrefcnt) AddRef(void); \
299 : NS_IMETHOD_(nsrefcnt) Release(void); \
300 : protected: \
301 : nsAutoRefCnt mRefCnt; \
302 : NS_DECL_OWNINGTHREAD \
303 : public:
304 :
305 : #define NS_DECL_CYCLE_COLLECTING_ISUPPORTS \
306 : public: \
307 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
308 : void** aInstancePtr); \
309 : NS_IMETHOD_(nsrefcnt) AddRef(void); \
310 : NS_IMETHOD_(nsrefcnt) Release(void); \
311 : void UnmarkIfPurple() \
312 : { \
313 : if (NS_LIKELY(mRefCnt.IsPurple())) \
314 : mRefCnt.unmarkPurple(); \
315 : } \
316 : protected: \
317 : nsCycleCollectingAutoRefCnt mRefCnt; \
318 : NS_DECL_OWNINGTHREAD \
319 : public:
320 :
321 :
322 : ///////////////////////////////////////////////////////////////////////////////
323 :
324 : /**
325 : * Previously used to initialize the reference count, but no longer needed.
326 : *
327 : * DEPRECATED.
328 : */
329 : #define NS_INIT_ISUPPORTS() ((void)0)
330 :
331 : /**
332 : * Use this macro to declare and implement the AddRef & Release methods for a
333 : * given non-XPCOM <i>_class</i>.
334 : *
335 : * @param _class The name of the class implementing the method
336 : */
337 : #define NS_INLINE_DECL_REFCOUNTING(_class) \
338 : public: \
339 : NS_METHOD_(nsrefcnt) AddRef(void) { \
340 : NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
341 : NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class); \
342 : ++mRefCnt; \
343 : NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
344 : return mRefCnt; \
345 : } \
346 : NS_METHOD_(nsrefcnt) Release(void) { \
347 : NS_PRECONDITION(0 != mRefCnt, "dup release"); \
348 : NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class); \
349 : --mRefCnt; \
350 : NS_LOG_RELEASE(this, mRefCnt, #_class); \
351 : if (mRefCnt == 0) { \
352 : NS_ASSERT_OWNINGTHREAD(_class); \
353 : mRefCnt = 1; /* stabilize */ \
354 : delete this; \
355 : return 0; \
356 : } \
357 : return mRefCnt; \
358 : } \
359 : protected: \
360 : nsAutoRefCnt mRefCnt; \
361 : NS_DECL_OWNINGTHREAD \
362 : public:
363 :
364 : /**
365 : * Use this macro to declare and implement the AddRef & Release methods for a
366 : * given non-XPCOM <i>_class</i> in a threadsafe manner.
367 : *
368 : * DOES NOT DO REFCOUNT STABILIZATION!
369 : *
370 : * @param _class The name of the class implementing the method
371 : */
372 : #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \
373 : public: \
374 : NS_METHOD_(nsrefcnt) AddRef(void) { \
375 : NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
376 : nsrefcnt count = NS_AtomicIncrementRefcnt(mRefCnt); \
377 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
378 : return (nsrefcnt) count; \
379 : } \
380 : NS_METHOD_(nsrefcnt) Release(void) { \
381 : NS_PRECONDITION(0 != mRefCnt, "dup release"); \
382 : nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt); \
383 : NS_LOG_RELEASE(this, count, #_class); \
384 : if (count == 0) { \
385 : delete (this); \
386 : return 0; \
387 : } \
388 : return count; \
389 : } \
390 : protected: \
391 : nsAutoRefCnt mRefCnt; \
392 : public:
393 :
394 : /**
395 : * Use this macro to implement the AddRef method for a given <i>_class</i>
396 : * @param _class The name of the class implementing the method
397 : */
398 : #define NS_IMPL_ADDREF(_class) \
399 : NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
400 : { \
401 : NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
402 : NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class); \
403 : ++mRefCnt; \
404 : NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
405 : return mRefCnt; \
406 : }
407 :
408 : /**
409 : * Use this macro to implement the AddRef method for a given <i>_class</i>
410 : * implemented as a wholly owned aggregated object intended to implement
411 : * interface(s) for its owner
412 : * @param _class The name of the class implementing the method
413 : * @param _aggregator the owning/containing object
414 : */
415 : #define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \
416 : NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
417 : { \
418 : NS_PRECONDITION(_aggregator, "null aggregator"); \
419 : return (_aggregator)->AddRef(); \
420 : }
421 :
422 : /**
423 : * Use this macro to implement the Release method for a given
424 : * <i>_class</i>.
425 : * @param _class The name of the class implementing the method
426 : * @param _destroy A statement that is executed when the object's
427 : * refcount drops to zero.
428 : *
429 : * For example,
430 : *
431 : * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
432 : *
433 : * will cause
434 : *
435 : * Destroy(this);
436 : *
437 : * to be invoked when the object's refcount drops to zero. This
438 : * allows for arbitrary teardown activity to occur (e.g., deallocation
439 : * of object allocated with placement new).
440 : */
441 : #define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
442 : NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
443 : { \
444 : NS_PRECONDITION(0 != mRefCnt, "dup release"); \
445 : NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class); \
446 : --mRefCnt; \
447 : NS_LOG_RELEASE(this, mRefCnt, #_class); \
448 : if (mRefCnt == 0) { \
449 : NS_ASSERT_OWNINGTHREAD(_class); \
450 : mRefCnt = 1; /* stabilize */ \
451 : _destroy; \
452 : return 0; \
453 : } \
454 : return mRefCnt; \
455 : }
456 :
457 : /**
458 : * Use this macro to implement the Release method for a given <i>_class</i>
459 : * @param _class The name of the class implementing the method
460 : *
461 : * A note on the 'stabilization' of the refcnt to one. At that point,
462 : * the object's refcount will have gone to zero. The object's
463 : * destructor may trigger code that attempts to QueryInterface() and
464 : * Release() 'this' again. Doing so will temporarily increment and
465 : * decrement the refcount. (Only a logic error would make one try to
466 : * keep a permanent hold on 'this'.) To prevent re-entering the
467 : * destructor, we make sure that no balanced refcounting can return
468 : * the refcount to |0|.
469 : */
470 : #define NS_IMPL_RELEASE(_class) \
471 : NS_IMPL_RELEASE_WITH_DESTROY(_class, delete (this))
472 :
473 : /**
474 : * Use this macro to implement the Release method for a given <i>_class</i>
475 : * implemented as a wholly owned aggregated object intended to implement
476 : * interface(s) for its owner
477 : * @param _class The name of the class implementing the method
478 : * @param _aggregator the owning/containing object
479 : */
480 : #define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \
481 : NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
482 : { \
483 : NS_PRECONDITION(_aggregator, "null aggregator"); \
484 : return (_aggregator)->Release(); \
485 : }
486 :
487 :
488 : #define NS_IMPL_CYCLE_COLLECTING_ADDREF(_class) \
489 : NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
490 : { \
491 : NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
492 : NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class); \
493 : nsrefcnt count = \
494 : mRefCnt.incr(NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this)); \
495 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
496 : return count; \
497 : }
498 :
499 : #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy) \
500 : NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
501 : { \
502 : NS_PRECONDITION(0 != mRefCnt, "dup release"); \
503 : NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class); \
504 : nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
505 : nsrefcnt count = mRefCnt.decr(base); \
506 : NS_LOG_RELEASE(this, count, #_class); \
507 : if (count == 0) { \
508 : NS_ASSERT_OWNINGTHREAD(_class); \
509 : mRefCnt.stabilizeForDeletion(base); \
510 : _destroy; \
511 : return 0; \
512 : } \
513 : return count; \
514 : }
515 :
516 : #define NS_IMPL_CYCLE_COLLECTING_RELEASE(_class) \
517 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, delete (this))
518 :
519 :
520 : ///////////////////////////////////////////////////////////////////////////////
521 :
522 : /**
523 : * There are two ways of implementing QueryInterface, and we use both:
524 : *
525 : * Table-driven QueryInterface uses a static table of IID->offset mappings
526 : * and a shared helper function. Using it tends to reduce codesize and improve
527 : * runtime performance (due to processor cache hits).
528 : *
529 : * Macro-driven QueryInterface generates a QueryInterface function directly
530 : * using common macros. This is necessary if special QueryInterface features
531 : * are being used (such as tearoffs and conditional interfaces).
532 : *
533 : * These methods can be combined into a table-driven function call followed
534 : * by custom code for tearoffs and conditionals.
535 : */
536 :
537 : struct QITableEntry
538 : {
539 : const nsIID *iid; // null indicates end of the QITableEntry array
540 : PROffset32 offset;
541 : };
542 :
543 : NS_COM_GLUE nsresult NS_FASTCALL
544 : NS_TableDrivenQI(void* aThis, const QITableEntry* entries,
545 : REFNSIID aIID, void **aInstancePtr);
546 :
547 : /**
548 : * Implement table-driven queryinterface
549 : */
550 :
551 : #define NS_INTERFACE_TABLE_HEAD(_class) \
552 : NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
553 : { \
554 : NS_ASSERTION(aInstancePtr, \
555 : "QueryInterface requires a non-NULL destination!"); \
556 : nsresult rv = NS_ERROR_FAILURE;
557 :
558 : #define NS_INTERFACE_TABLE_BEGIN \
559 : static const QITableEntry table[] = {
560 :
561 : #define NS_INTERFACE_TABLE_ENTRY(_class, _interface) \
562 : { &_interface::COMTypeInfo<int>::kIID, \
563 : PROffset32(reinterpret_cast<char*>( \
564 : static_cast<_interface*>((_class*) 0x1000)) - \
565 : reinterpret_cast<char*>((_class*) 0x1000)) \
566 : },
567 :
568 : #define NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, _interface, _implClass) \
569 : { &_interface::COMTypeInfo<int>::kIID, \
570 : PROffset32(reinterpret_cast<char*>( \
571 : static_cast<_interface*>( \
572 : static_cast<_implClass*>( \
573 : (_class*) 0x1000))) - \
574 : reinterpret_cast<char*>((_class*) 0x1000)) \
575 : },
576 :
577 : #define NS_INTERFACE_TABLE_END_WITH_PTR(_ptr) \
578 : { nsnull, 0 } }; \
579 : rv = NS_TableDrivenQI(static_cast<void*>(_ptr), \
580 : table, aIID, aInstancePtr);
581 :
582 : #define NS_INTERFACE_TABLE_END \
583 : NS_INTERFACE_TABLE_END_WITH_PTR(this)
584 :
585 : #define NS_INTERFACE_TABLE_TAIL \
586 : return rv; \
587 : }
588 :
589 : #define NS_INTERFACE_TABLE_TAIL_INHERITING(_baseclass) \
590 : if (NS_SUCCEEDED(rv)) \
591 : return rv; \
592 : return _baseclass::QueryInterface(aIID, aInstancePtr); \
593 : }
594 :
595 : #define NS_INTERFACE_TABLE_TAIL_USING_AGGREGATOR(_aggregator) \
596 : if (NS_SUCCEEDED(rv)) \
597 : return rv; \
598 : NS_ASSERTION(_aggregator, "null aggregator"); \
599 : return _aggregator->QueryInterface(aIID, aInstancePtr) \
600 : }
601 :
602 : /**
603 : * This implements query interface with two assumptions: First, the
604 : * class in question implements nsISupports and its own interface and
605 : * nothing else. Second, the implementation of the class's primary
606 : * inheritance chain leads to its own interface.
607 : *
608 : * @param _class The name of the class implementing the method
609 : * @param _classiiddef The name of the #define symbol that defines the IID
610 : * for the class (e.g. NS_ISUPPORTS_IID)
611 : */
612 :
613 : #define NS_IMPL_QUERY_HEAD(_class) \
614 : NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
615 : { \
616 : NS_ASSERTION(aInstancePtr, \
617 : "QueryInterface requires a non-NULL destination!"); \
618 : nsISupports* foundInterface;
619 :
620 : #define NS_IMPL_QUERY_BODY(_interface) \
621 : if ( aIID.Equals(NS_GET_IID(_interface)) ) \
622 : foundInterface = static_cast<_interface*>(this); \
623 : else
624 :
625 : #define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \
626 : if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \
627 : foundInterface = static_cast<_interface*>(this); \
628 : else
629 :
630 : #define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \
631 : if ( aIID.Equals(NS_GET_IID(_interface)) ) \
632 : foundInterface = static_cast<_interface*>( \
633 : static_cast<_implClass*>(this)); \
634 : else
635 :
636 : #define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \
637 : if ( aIID.Equals(NS_GET_IID(_interface)) ) \
638 : foundInterface = static_cast<_interface*>(_aggregate); \
639 : else
640 :
641 : #define NS_IMPL_QUERY_TAIL_GUTS \
642 : foundInterface = 0; \
643 : nsresult status; \
644 : if ( !foundInterface ) \
645 : status = NS_NOINTERFACE; \
646 : else \
647 : { \
648 : NS_ADDREF(foundInterface); \
649 : status = NS_OK; \
650 : } \
651 : *aInstancePtr = foundInterface; \
652 : return status; \
653 : }
654 :
655 : #define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \
656 : foundInterface = 0; \
657 : nsresult status; \
658 : if ( !foundInterface ) \
659 : status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \
660 : else \
661 : { \
662 : NS_ADDREF(foundInterface); \
663 : status = NS_OK; \
664 : } \
665 : *aInstancePtr = foundInterface; \
666 : return status; \
667 : }
668 :
669 : #define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \
670 : foundInterface = 0; \
671 : nsresult status; \
672 : if ( !foundInterface ) { \
673 : NS_ASSERTION(_aggregator, "null aggregator"); \
674 : status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \
675 : } else \
676 : { \
677 : NS_ADDREF(foundInterface); \
678 : status = NS_OK; \
679 : } \
680 : *aInstancePtr = foundInterface; \
681 : return status; \
682 : }
683 :
684 : #define NS_IMPL_QUERY_TAIL(_supports_interface) \
685 : NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \
686 : NS_IMPL_QUERY_TAIL_GUTS
687 :
688 :
689 : /*
690 : This is the new scheme. Using this notation now will allow us to switch to
691 : a table driven mechanism when it's ready. Note the difference between this
692 : and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must
693 : explicitly mention |nsISupports| when using the interface maps.
694 : */
695 : #define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass)
696 : #define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface)
697 : #define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \
698 : NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
699 : #define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \
700 : NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
701 :
702 : #define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS
703 : #define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \
704 : NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
705 : #define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \
706 : NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
707 : #define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \
708 : NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
709 :
710 : #define NS_INTERFACE_TABLE0(_class) \
711 : NS_INTERFACE_TABLE_BEGIN \
712 : NS_INTERFACE_TABLE_ENTRY(_class, nsISupports) \
713 : NS_INTERFACE_TABLE_END
714 :
715 : #define NS_INTERFACE_TABLE1(_class, _i1) \
716 : NS_INTERFACE_TABLE_BEGIN \
717 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
718 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
719 : NS_INTERFACE_TABLE_END
720 :
721 : #define NS_INTERFACE_TABLE2(_class, _i1, _i2) \
722 : NS_INTERFACE_TABLE_BEGIN \
723 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
724 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
725 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
726 : NS_INTERFACE_TABLE_END
727 :
728 : #define NS_INTERFACE_TABLE3(_class, _i1, _i2, _i3) \
729 : NS_INTERFACE_TABLE_BEGIN \
730 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
731 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
732 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
733 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
734 : NS_INTERFACE_TABLE_END
735 :
736 : #define NS_INTERFACE_TABLE4(_class, _i1, _i2, _i3, _i4) \
737 : NS_INTERFACE_TABLE_BEGIN \
738 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
739 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
740 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
741 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
742 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
743 : NS_INTERFACE_TABLE_END
744 :
745 : #define NS_INTERFACE_TABLE5(_class, _i1, _i2, _i3, _i4, _i5) \
746 : NS_INTERFACE_TABLE_BEGIN \
747 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
748 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
749 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
750 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
751 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
752 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
753 : NS_INTERFACE_TABLE_END
754 :
755 : #define NS_INTERFACE_TABLE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
756 : NS_INTERFACE_TABLE_BEGIN \
757 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
758 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
759 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
760 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
761 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
762 : NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
763 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
764 : NS_INTERFACE_TABLE_END
765 :
766 : #define NS_INTERFACE_TABLE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
767 : NS_INTERFACE_TABLE_BEGIN \
768 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
769 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
770 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
771 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
772 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
773 : NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
774 : NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
775 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
776 : NS_INTERFACE_TABLE_END
777 :
778 : #define NS_INTERFACE_TABLE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
779 : NS_INTERFACE_TABLE_BEGIN \
780 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
781 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
782 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
783 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
784 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
785 : NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
786 : NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
787 : NS_INTERFACE_TABLE_ENTRY(_class, _i8) \
788 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
789 : NS_INTERFACE_TABLE_END
790 :
791 : #define NS_INTERFACE_TABLE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
792 : _i8, _i9) \
793 : NS_INTERFACE_TABLE_BEGIN \
794 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
795 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
796 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
797 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
798 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
799 : NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
800 : NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
801 : NS_INTERFACE_TABLE_ENTRY(_class, _i8) \
802 : NS_INTERFACE_TABLE_ENTRY(_class, _i9) \
803 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
804 : NS_INTERFACE_TABLE_END
805 :
806 : #define NS_INTERFACE_TABLE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
807 : _i8, _i9, _i10) \
808 : NS_INTERFACE_TABLE_BEGIN \
809 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
810 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
811 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
812 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
813 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
814 : NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
815 : NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
816 : NS_INTERFACE_TABLE_ENTRY(_class, _i8) \
817 : NS_INTERFACE_TABLE_ENTRY(_class, _i9) \
818 : NS_INTERFACE_TABLE_ENTRY(_class, _i10) \
819 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
820 : NS_INTERFACE_TABLE_END
821 :
822 : #define NS_INTERFACE_TABLE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
823 : _i8, _i9, _i10, _i11) \
824 : NS_INTERFACE_TABLE_BEGIN \
825 : NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
826 : NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
827 : NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
828 : NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
829 : NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
830 : NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
831 : NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
832 : NS_INTERFACE_TABLE_ENTRY(_class, _i8) \
833 : NS_INTERFACE_TABLE_ENTRY(_class, _i9) \
834 : NS_INTERFACE_TABLE_ENTRY(_class, _i10) \
835 : NS_INTERFACE_TABLE_ENTRY(_class, _i11) \
836 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1) \
837 : NS_INTERFACE_TABLE_END
838 :
839 : #define NS_IMPL_QUERY_INTERFACE0(_class) \
840 : NS_INTERFACE_TABLE_HEAD(_class) \
841 : NS_INTERFACE_TABLE0(_class) \
842 : NS_INTERFACE_TABLE_TAIL
843 :
844 : #define NS_IMPL_QUERY_INTERFACE1(_class, _i1) \
845 : NS_INTERFACE_TABLE_HEAD(_class) \
846 : NS_INTERFACE_TABLE1(_class, _i1) \
847 : NS_INTERFACE_TABLE_TAIL
848 :
849 : #define NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2) \
850 : NS_INTERFACE_TABLE_HEAD(_class) \
851 : NS_INTERFACE_TABLE2(_class, _i1, _i2) \
852 : NS_INTERFACE_TABLE_TAIL
853 :
854 : #define NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3) \
855 : NS_INTERFACE_TABLE_HEAD(_class) \
856 : NS_INTERFACE_TABLE3(_class, _i1, _i2, _i3) \
857 : NS_INTERFACE_TABLE_TAIL
858 :
859 : #define NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4) \
860 : NS_INTERFACE_TABLE_HEAD(_class) \
861 : NS_INTERFACE_TABLE4(_class, _i1, _i2, _i3, _i4) \
862 : NS_INTERFACE_TABLE_TAIL
863 :
864 : #define NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5) \
865 : NS_INTERFACE_TABLE_HEAD(_class) \
866 : NS_INTERFACE_TABLE5(_class, _i1, _i2, _i3, _i4, _i5) \
867 : NS_INTERFACE_TABLE_TAIL
868 :
869 : #define NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
870 : NS_INTERFACE_TABLE_HEAD(_class) \
871 : NS_INTERFACE_TABLE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
872 : NS_INTERFACE_TABLE_TAIL
873 :
874 : #define NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
875 : NS_INTERFACE_TABLE_HEAD(_class) \
876 : NS_INTERFACE_TABLE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
877 : NS_INTERFACE_TABLE_TAIL
878 :
879 : #define NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
880 : _i7, _i8) \
881 : NS_INTERFACE_TABLE_HEAD(_class) \
882 : NS_INTERFACE_TABLE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
883 : NS_INTERFACE_TABLE_TAIL
884 :
885 : #define NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
886 : _i7, _i8, _i9) \
887 : NS_INTERFACE_TABLE_HEAD(_class) \
888 : NS_INTERFACE_TABLE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9) \
889 : NS_INTERFACE_TABLE_TAIL
890 :
891 : #define NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
892 : _i7, _i8, _i9, _i10) \
893 : NS_INTERFACE_TABLE_HEAD(_class) \
894 : NS_INTERFACE_TABLE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
895 : _i9, _i10) \
896 : NS_INTERFACE_TABLE_TAIL
897 :
898 : #define NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
899 : _i7, _i8, _i9, _i10, _i11) \
900 : NS_INTERFACE_TABLE_HEAD(_class) \
901 : NS_INTERFACE_TABLE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
902 : _i9, _i10, _i11) \
903 : NS_INTERFACE_TABLE_TAIL
904 :
905 :
906 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE0 NS_IMPL_QUERY_INTERFACE0
907 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE1 NS_IMPL_QUERY_INTERFACE1
908 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE2 NS_IMPL_QUERY_INTERFACE2
909 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE3 NS_IMPL_QUERY_INTERFACE3
910 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE4 NS_IMPL_QUERY_INTERFACE4
911 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE5 NS_IMPL_QUERY_INTERFACE5
912 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE6 NS_IMPL_QUERY_INTERFACE6
913 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE7 NS_IMPL_QUERY_INTERFACE7
914 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE8 NS_IMPL_QUERY_INTERFACE8
915 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE9 NS_IMPL_QUERY_INTERFACE9
916 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE10 NS_IMPL_QUERY_INTERFACE10
917 : #define NS_IMPL_THREADSAFE_QUERY_INTERFACE11 NS_IMPL_QUERY_INTERFACE11
918 :
919 : /**
920 : * Declare that you're going to inherit from something that already
921 : * implements nsISupports, but also implements an additional interface, thus
922 : * causing an ambiguity. In this case you don't need another mRefCnt, you
923 : * just need to forward the definitions to the appropriate superclass. E.g.
924 : *
925 : * class Bar : public Foo, public nsIBar { // both provide nsISupports
926 : * public:
927 : * NS_DECL_ISUPPORTS_INHERITED
928 : * ...other nsIBar and Bar methods...
929 : * };
930 : */
931 : #define NS_DECL_ISUPPORTS_INHERITED \
932 : public: \
933 : NS_IMETHOD QueryInterface(REFNSIID aIID, \
934 : void** aInstancePtr); \
935 : NS_IMETHOD_(nsrefcnt) AddRef(void); \
936 : NS_IMETHOD_(nsrefcnt) Release(void); \
937 :
938 : /**
939 : * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
940 : * to implement the nsISupports methods, forwarding the invocations to a
941 : * superclass that already implements nsISupports.
942 : *
943 : * Note that I didn't make these inlined because they're virtual methods.
944 : */
945 :
946 : #define NS_IMPL_ADDREF_INHERITED(Class, Super) \
947 : NS_IMETHODIMP_(nsrefcnt) Class::AddRef(void) \
948 : { \
949 : nsrefcnt r = Super::AddRef(); \
950 : NS_LOG_ADDREF(this, r, #Class, sizeof(*this)); \
951 : return r; \
952 : }
953 :
954 : #define NS_IMPL_RELEASE_INHERITED(Class, Super) \
955 : NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \
956 : { \
957 : nsrefcnt r = Super::Release(); \
958 : NS_LOG_RELEASE(this, r, #Class); \
959 : return r; \
960 : }
961 :
962 : /**
963 : * As above but not logging the addref/release; needed if the base
964 : * class might be aggregated.
965 : */
966 : #define NS_IMPL_NONLOGGING_ADDREF_INHERITED(Class, Super) \
967 : NS_IMETHODIMP_(nsrefcnt) Class::AddRef(void) \
968 : { \
969 : return Super::AddRef(); \
970 : }
971 :
972 : #define NS_IMPL_NONLOGGING_RELEASE_INHERITED(Class, Super) \
973 : NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \
974 : { \
975 : return Super::Release(); \
976 : }
977 :
978 : #define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */
979 :
980 : #define NS_INTERFACE_TABLE_INHERITED1(Class, i1) \
981 : NS_INTERFACE_TABLE_BEGIN \
982 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
983 : NS_INTERFACE_TABLE_END
984 :
985 : #define NS_INTERFACE_TABLE_INHERITED2(Class, i1, i2) \
986 : NS_INTERFACE_TABLE_BEGIN \
987 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
988 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
989 : NS_INTERFACE_TABLE_END
990 :
991 : #define NS_INTERFACE_TABLE_INHERITED3(Class, i1, i2, i3) \
992 : NS_INTERFACE_TABLE_BEGIN \
993 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
994 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
995 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
996 : NS_INTERFACE_TABLE_END
997 :
998 : #define NS_INTERFACE_TABLE_INHERITED4(Class, i1, i2, i3, i4) \
999 : NS_INTERFACE_TABLE_BEGIN \
1000 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1001 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1002 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1003 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1004 : NS_INTERFACE_TABLE_END
1005 :
1006 : #define NS_INTERFACE_TABLE_INHERITED5(Class, i1, i2, i3, i4, i5) \
1007 : NS_INTERFACE_TABLE_BEGIN \
1008 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1009 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1010 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1011 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1012 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1013 : NS_INTERFACE_TABLE_END
1014 :
1015 : #define NS_INTERFACE_TABLE_INHERITED6(Class, i1, i2, i3, i4, i5, i6) \
1016 : NS_INTERFACE_TABLE_BEGIN \
1017 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1018 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1019 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1020 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1021 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1022 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1023 : NS_INTERFACE_TABLE_END
1024 :
1025 : #define NS_INTERFACE_TABLE_INHERITED7(Class, i1, i2, i3, i4, i5, i6, i7) \
1026 : NS_INTERFACE_TABLE_BEGIN \
1027 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1028 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1029 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1030 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1031 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1032 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1033 : NS_INTERFACE_TABLE_ENTRY(Class, i7) \
1034 : NS_INTERFACE_TABLE_END
1035 :
1036 : #define NS_INTERFACE_TABLE_INHERITED8(Class, i1, i2, i3, i4, i5, i6, i7, i8) \
1037 : NS_INTERFACE_TABLE_BEGIN \
1038 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1039 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1040 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1041 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1042 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1043 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1044 : NS_INTERFACE_TABLE_ENTRY(Class, i7) \
1045 : NS_INTERFACE_TABLE_ENTRY(Class, i8) \
1046 : NS_INTERFACE_TABLE_END
1047 :
1048 : #define NS_INTERFACE_TABLE_INHERITED9(Class, i1, i2, i3, i4, i5, i6, i7, \
1049 : i8, i9) \
1050 : NS_INTERFACE_TABLE_BEGIN \
1051 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1052 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1053 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1054 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1055 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1056 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1057 : NS_INTERFACE_TABLE_ENTRY(Class, i7) \
1058 : NS_INTERFACE_TABLE_ENTRY(Class, i8) \
1059 : NS_INTERFACE_TABLE_ENTRY(Class, i9) \
1060 : NS_INTERFACE_TABLE_END
1061 :
1062 : #define NS_INTERFACE_TABLE_INHERITED10(Class, i1, i2, i3, i4, i5, i6, i7, \
1063 : i8, i9, i10) \
1064 : NS_INTERFACE_TABLE_BEGIN \
1065 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1066 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1067 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1068 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1069 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1070 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1071 : NS_INTERFACE_TABLE_ENTRY(Class, i7) \
1072 : NS_INTERFACE_TABLE_ENTRY(Class, i8) \
1073 : NS_INTERFACE_TABLE_ENTRY(Class, i9) \
1074 : NS_INTERFACE_TABLE_ENTRY(Class, i10) \
1075 : NS_INTERFACE_TABLE_END
1076 :
1077 : #define NS_INTERFACE_TABLE_INHERITED11(Class, i1, i2, i3, i4, i5, i6, i7, \
1078 : i8, i9, i10, i11) \
1079 : NS_INTERFACE_TABLE_BEGIN \
1080 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1081 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1082 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1083 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1084 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1085 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1086 : NS_INTERFACE_TABLE_ENTRY(Class, i7) \
1087 : NS_INTERFACE_TABLE_ENTRY(Class, i8) \
1088 : NS_INTERFACE_TABLE_ENTRY(Class, i9) \
1089 : NS_INTERFACE_TABLE_ENTRY(Class, i10) \
1090 : NS_INTERFACE_TABLE_ENTRY(Class, i11) \
1091 : NS_INTERFACE_TABLE_END
1092 :
1093 : #define NS_INTERFACE_TABLE_INHERITED12(Class, i1, i2, i3, i4, i5, i6, i7, \
1094 : i8, i9, i10, i11, i12) \
1095 : NS_INTERFACE_TABLE_BEGIN \
1096 : NS_INTERFACE_TABLE_ENTRY(Class, i1) \
1097 : NS_INTERFACE_TABLE_ENTRY(Class, i2) \
1098 : NS_INTERFACE_TABLE_ENTRY(Class, i3) \
1099 : NS_INTERFACE_TABLE_ENTRY(Class, i4) \
1100 : NS_INTERFACE_TABLE_ENTRY(Class, i5) \
1101 : NS_INTERFACE_TABLE_ENTRY(Class, i6) \
1102 : NS_INTERFACE_TABLE_ENTRY(Class, i7) \
1103 : NS_INTERFACE_TABLE_ENTRY(Class, i8) \
1104 : NS_INTERFACE_TABLE_ENTRY(Class, i9) \
1105 : NS_INTERFACE_TABLE_ENTRY(Class, i10) \
1106 : NS_INTERFACE_TABLE_ENTRY(Class, i11) \
1107 : NS_INTERFACE_TABLE_ENTRY(Class, i12) \
1108 : NS_INTERFACE_TABLE_END
1109 :
1110 : #define NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \
1111 : NS_INTERFACE_TABLE_HEAD(Class) \
1112 : NS_INTERFACE_TABLE_INHERITED0(Class) \
1113 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1114 :
1115 : #define NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \
1116 : NS_INTERFACE_TABLE_HEAD(Class) \
1117 : NS_INTERFACE_TABLE_INHERITED1(Class, i1) \
1118 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1119 :
1120 : #define NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \
1121 : NS_INTERFACE_TABLE_HEAD(Class) \
1122 : NS_INTERFACE_TABLE_INHERITED2(Class, i1, i2) \
1123 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1124 :
1125 : #define NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \
1126 : NS_INTERFACE_TABLE_HEAD(Class) \
1127 : NS_INTERFACE_TABLE_INHERITED3(Class, i1, i2, i3) \
1128 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1129 :
1130 : #define NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \
1131 : NS_INTERFACE_TABLE_HEAD(Class) \
1132 : NS_INTERFACE_TABLE_INHERITED4(Class, i1, i2, i3, i4) \
1133 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1134 :
1135 : #define NS_IMPL_QUERY_INTERFACE_INHERITED5(Class,Super,i1,i2,i3,i4,i5) \
1136 : NS_INTERFACE_TABLE_HEAD(Class) \
1137 : NS_INTERFACE_TABLE_INHERITED5(Class, i1, i2, i3, i4, i5) \
1138 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1139 :
1140 : #define NS_IMPL_QUERY_INTERFACE_INHERITED6(Class,Super,i1,i2,i3,i4,i5,i6) \
1141 : NS_INTERFACE_TABLE_HEAD(Class) \
1142 : NS_INTERFACE_TABLE_INHERITED6(Class, i1, i2, i3, i4, i5, i6) \
1143 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1144 :
1145 : #define NS_IMPL_QUERY_INTERFACE_INHERITED7(Class,Super,i1,i2,i3,i4,i5,i6,i7) \
1146 : NS_INTERFACE_TABLE_HEAD(Class) \
1147 : NS_INTERFACE_TABLE_INHERITED7(Class, i1, i2, i3, i4, i5, i6, i7) \
1148 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1149 :
1150 : #define NS_IMPL_QUERY_INTERFACE_INHERITED8(Class,Super,i1,i2,i3,i4,i5,i6, \
1151 : i7,i8) \
1152 : NS_INTERFACE_TABLE_HEAD(Class) \
1153 : NS_INTERFACE_TABLE_INHERITED8(Class, i1, i2, i3, i4, i5, i6, i7, i8) \
1154 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1155 :
1156 : #define NS_IMPL_QUERY_INTERFACE_INHERITED9(Class,Super,i1,i2,i3,i4,i5,i6, \
1157 : i7,i8,i9) \
1158 : NS_INTERFACE_TABLE_HEAD(Class) \
1159 : NS_INTERFACE_TABLE_INHERITED9(Class, i1, i2, i3, i4, i5, i6, i7, i8, i9) \
1160 : NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
1161 :
1162 : /**
1163 : * Convenience macros for implementing all nsISupports methods for
1164 : * a simple class.
1165 : * @param _class The name of the class implementing the method
1166 : * @param _classiiddef The name of the #define symbol that defines the IID
1167 : * for the class (e.g. NS_ISUPPORTS_IID)
1168 : */
1169 :
1170 : #define NS_IMPL_ISUPPORTS0(_class) \
1171 : NS_IMPL_ADDREF(_class) \
1172 : NS_IMPL_RELEASE(_class) \
1173 : NS_IMPL_QUERY_INTERFACE0(_class)
1174 :
1175 : #define NS_IMPL_ISUPPORTS1(_class, _interface) \
1176 : NS_IMPL_ADDREF(_class) \
1177 : NS_IMPL_RELEASE(_class) \
1178 : NS_IMPL_QUERY_INTERFACE1(_class, _interface)
1179 :
1180 : #define NS_IMPL_ISUPPORTS2(_class, _i1, _i2) \
1181 : NS_IMPL_ADDREF(_class) \
1182 : NS_IMPL_RELEASE(_class) \
1183 : NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2)
1184 :
1185 : #define NS_IMPL_ISUPPORTS3(_class, _i1, _i2, _i3) \
1186 : NS_IMPL_ADDREF(_class) \
1187 : NS_IMPL_RELEASE(_class) \
1188 : NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3)
1189 :
1190 : #define NS_IMPL_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \
1191 : NS_IMPL_ADDREF(_class) \
1192 : NS_IMPL_RELEASE(_class) \
1193 : NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4)
1194 :
1195 : #define NS_IMPL_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \
1196 : NS_IMPL_ADDREF(_class) \
1197 : NS_IMPL_RELEASE(_class) \
1198 : NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5)
1199 :
1200 : #define NS_IMPL_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
1201 : NS_IMPL_ADDREF(_class) \
1202 : NS_IMPL_RELEASE(_class) \
1203 : NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
1204 :
1205 : #define NS_IMPL_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
1206 : NS_IMPL_ADDREF(_class) \
1207 : NS_IMPL_RELEASE(_class) \
1208 : NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7)
1209 :
1210 : #define NS_IMPL_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
1211 : NS_IMPL_ADDREF(_class) \
1212 : NS_IMPL_RELEASE(_class) \
1213 : NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)
1214 :
1215 : #define NS_IMPL_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
1216 : _i9) \
1217 : NS_IMPL_ADDREF(_class) \
1218 : NS_IMPL_RELEASE(_class) \
1219 : NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9)
1220 :
1221 : #define NS_IMPL_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
1222 : _i9, _i10) \
1223 : NS_IMPL_ADDREF(_class) \
1224 : NS_IMPL_RELEASE(_class) \
1225 : NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
1226 : _i9, _i10)
1227 :
1228 : #define NS_IMPL_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
1229 : _i9, _i10, _i11) \
1230 : NS_IMPL_ADDREF(_class) \
1231 : NS_IMPL_RELEASE(_class) \
1232 : NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
1233 : _i9, _i10, _i11)
1234 :
1235 : #define NS_IMPL_ISUPPORTS_INHERITED0(Class, Super) \
1236 : NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \
1237 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1238 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1239 :
1240 : #define NS_IMPL_ISUPPORTS_INHERITED1(Class, Super, i1) \
1241 : NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \
1242 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1243 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1244 :
1245 : #define NS_IMPL_ISUPPORTS_INHERITED2(Class, Super, i1, i2) \
1246 : NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \
1247 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1248 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1249 :
1250 : #define NS_IMPL_ISUPPORTS_INHERITED3(Class, Super, i1, i2, i3) \
1251 : NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \
1252 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1253 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1254 :
1255 : #define NS_IMPL_ISUPPORTS_INHERITED4(Class, Super, i1, i2, i3, i4) \
1256 : NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \
1257 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1258 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1259 :
1260 : #define NS_IMPL_ISUPPORTS_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \
1261 : NS_IMPL_QUERY_INTERFACE_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \
1262 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1263 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1264 :
1265 : #define NS_IMPL_ISUPPORTS_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \
1266 : NS_IMPL_QUERY_INTERFACE_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \
1267 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1268 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1269 :
1270 : #define NS_IMPL_ISUPPORTS_INHERITED7(Class, Super, i1, i2, i3, i4, i5, i6, i7) \
1271 : NS_IMPL_QUERY_INTERFACE_INHERITED7(Class, Super, i1, i2, i3, i4, i5, i6, i7) \
1272 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1273 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1274 :
1275 : #define NS_IMPL_ISUPPORTS_INHERITED8(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8) \
1276 : NS_IMPL_QUERY_INTERFACE_INHERITED8(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8) \
1277 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1278 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1279 :
1280 : #define NS_IMPL_ISUPPORTS_INHERITED9(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8, i9) \
1281 : NS_IMPL_QUERY_INTERFACE_INHERITED9(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8, i9) \
1282 : NS_IMPL_ADDREF_INHERITED(Class, Super) \
1283 : NS_IMPL_RELEASE_INHERITED(Class, Super) \
1284 : /*
1285 : * Macro to glue together a QI that starts with an interface table
1286 : * and segues into an interface map (e.g. it uses singleton classinfo
1287 : * or tearoffs).
1288 : */
1289 : #define NS_INTERFACE_TABLE_TO_MAP_SEGUE \
1290 : if (rv == NS_OK) return rv; \
1291 : nsISupports* foundInterface;
1292 :
1293 :
1294 : ///////////////////////////////////////////////////////////////////////////////
1295 : /**
1296 : *
1297 : * Threadsafe implementations of the ISupports convenience macros.
1298 : *
1299 : * @note These are not available when linking against the standalone glue,
1300 : * because the implementation requires PR_ symbols.
1301 : */
1302 :
1303 : #if !defined(XPCOM_GLUE_AVOID_NSPR)
1304 :
1305 : /**
1306 : * Use this macro to implement the AddRef method for a given <i>_class</i>
1307 : * @param _class The name of the class implementing the method
1308 : */
1309 :
1310 : #define NS_IMPL_THREADSAFE_ADDREF(_class) \
1311 : NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
1312 : { \
1313 : NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
1314 : nsrefcnt count = NS_AtomicIncrementRefcnt(mRefCnt); \
1315 : NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
1316 : return (nsrefcnt) count; \
1317 : }
1318 :
1319 : /**
1320 : * Use this macro to implement the Release method for a given <i>_class</i>
1321 : * @param _class The name of the class implementing the method
1322 : *
1323 : * Note that we don't need to use an atomic operation to stabilize the refcnt.
1324 : * If the refcnt is released to 0, only the current thread has a reference to
1325 : * the object; we thus don't have to use an atomic set to inform other threads
1326 : * that we've changed the refcnt.
1327 : */
1328 :
1329 : #define NS_IMPL_THREADSAFE_RELEASE(_class) \
1330 : NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
1331 : { \
1332 : NS_PRECONDITION(0 != mRefCnt, "dup release"); \
1333 : nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt); \
1334 : NS_LOG_RELEASE(this, count, #_class); \
1335 : if (0 == count) { \
1336 : mRefCnt = 1; /* stabilize */ \
1337 : /* enable this to find non-threadsafe destructors: */ \
1338 : /* NS_ASSERT_OWNINGTHREAD(_class); */ \
1339 : delete (this); \
1340 : return 0; \
1341 : } \
1342 : return count; \
1343 : }
1344 :
1345 : #else // XPCOM_GLUE_AVOID_NSPR
1346 :
1347 : #define NS_IMPL_THREADSAFE_ADDREF(_class) \
1348 : THREADSAFE_ISUPPORTS_NOT_AVAILABLE_IN_STANDALONE_GLUE;
1349 :
1350 : #define NS_IMPL_THREADSAFE_RELEASE(_class) \
1351 : THREADSAFE_ISUPPORTS_NOT_AVAILABLE_IN_STANDALONE_GLUE;
1352 :
1353 : #endif
1354 :
1355 : #define NS_IMPL_THREADSAFE_ISUPPORTS0(_class) \
1356 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1357 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1358 : NS_IMPL_THREADSAFE_QUERY_INTERFACE0(_class)
1359 :
1360 : #define NS_IMPL_THREADSAFE_ISUPPORTS1(_class, _interface) \
1361 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1362 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1363 : NS_IMPL_THREADSAFE_QUERY_INTERFACE1(_class, _interface)
1364 :
1365 : #define NS_IMPL_THREADSAFE_ISUPPORTS2(_class, _i1, _i2) \
1366 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1367 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1368 : NS_IMPL_THREADSAFE_QUERY_INTERFACE2(_class, _i1, _i2)
1369 :
1370 : #define NS_IMPL_THREADSAFE_ISUPPORTS3(_class, _i1, _i2, _i3) \
1371 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1372 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1373 : NS_IMPL_THREADSAFE_QUERY_INTERFACE3(_class, _i1, _i2, _i3)
1374 :
1375 : #define NS_IMPL_THREADSAFE_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \
1376 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1377 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1378 : NS_IMPL_THREADSAFE_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4)
1379 :
1380 : #define NS_IMPL_THREADSAFE_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \
1381 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1382 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1383 : NS_IMPL_THREADSAFE_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5)
1384 :
1385 : #define NS_IMPL_THREADSAFE_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
1386 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1387 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1388 : NS_IMPL_THREADSAFE_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
1389 :
1390 : #define NS_IMPL_THREADSAFE_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1391 : _i7) \
1392 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1393 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1394 : NS_IMPL_THREADSAFE_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1395 : _i7)
1396 :
1397 : #define NS_IMPL_THREADSAFE_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1398 : _i7, _i8) \
1399 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1400 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1401 : NS_IMPL_THREADSAFE_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1402 : _i7, _i8)
1403 :
1404 : #define NS_IMPL_THREADSAFE_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1405 : _i7, _i8, _i9) \
1406 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1407 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1408 : NS_IMPL_THREADSAFE_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1409 : _i7, _i8, _i9)
1410 :
1411 : #define NS_IMPL_THREADSAFE_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1412 : _i7, _i8, _i9, _i10) \
1413 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1414 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1415 : NS_IMPL_THREADSAFE_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1416 : _i7, _i8, _i9, _i10)
1417 :
1418 : #define NS_IMPL_THREADSAFE_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1419 : _i7, _i8, _i9, _i10, _i11) \
1420 : NS_IMPL_THREADSAFE_ADDREF(_class) \
1421 : NS_IMPL_THREADSAFE_RELEASE(_class) \
1422 : NS_IMPL_THREADSAFE_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
1423 : _i7, _i8, _i9, _i10, _i11)
1424 :
1425 : #define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
1426 :
1427 : /**
1428 : * Macro to generate nsIClassInfo methods for classes which do not have
1429 : * corresponding nsIFactory implementations.
1430 : */
1431 : #define NS_IMPL_THREADSAFE_CI(_class) \
1432 : NS_IMETHODIMP \
1433 : _class::GetInterfaces(PRUint32* _count, nsIID*** _array) \
1434 : { \
1435 : return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \
1436 : } \
1437 : \
1438 : NS_IMETHODIMP \
1439 : _class::GetHelperForLanguage(PRUint32 _language, nsISupports** _retval) \
1440 : { \
1441 : *_retval = nsnull; \
1442 : return NS_OK; \
1443 : } \
1444 : \
1445 : NS_IMETHODIMP \
1446 : _class::GetContractID(char** _contractID) \
1447 : { \
1448 : *_contractID = nsnull; \
1449 : return NS_OK; \
1450 : } \
1451 : \
1452 : NS_IMETHODIMP \
1453 : _class::GetClassDescription(char** _classDescription) \
1454 : { \
1455 : *_classDescription = nsnull; \
1456 : return NS_OK; \
1457 : } \
1458 : \
1459 : NS_IMETHODIMP \
1460 : _class::GetClassID(nsCID** _classID) \
1461 : { \
1462 : *_classID = nsnull; \
1463 : return NS_OK; \
1464 : } \
1465 : \
1466 : NS_IMETHODIMP \
1467 : _class::GetImplementationLanguage(PRUint32* _language) \
1468 : { \
1469 : *_language = nsIProgrammingLanguage::CPLUSPLUS; \
1470 : return NS_OK; \
1471 : } \
1472 : \
1473 : NS_IMETHODIMP \
1474 : _class::GetFlags(PRUint32* _flags) \
1475 : { \
1476 : *_flags = nsIClassInfo::THREADSAFE; \
1477 : return NS_OK; \
1478 : } \
1479 : \
1480 : NS_IMETHODIMP \
1481 : _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
1482 : { \
1483 : return NS_ERROR_NOT_AVAILABLE; \
1484 : }
1485 :
1486 : #endif
|