Bug 1910362 - Create new Nimbus helper r=aaronmt,ohorvath
[gecko.git] / xpcom / base / nsISupportsImpl.cpp
blob5ae4b3914bb752399fb2a2567720ff1f52039e33
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/. */
7 #include "nsISupportsImpl.h"
9 #include "mozilla/Assertions.h"
10 #ifndef XPCOM_GLUE_AVOID_NSPR
11 # include "nsPrintfCString.h"
12 # include "nsThreadUtils.h"
13 #endif
15 using namespace mozilla;
17 nsresult NS_FASTCALL NS_TableDrivenQI(void* aThis, REFNSIID aIID,
18 void** aInstancePtr,
19 const QITableEntry* aEntries) {
20 do {
21 if (aIID.Equals(*aEntries->iid)) {
22 nsISupports* r = reinterpret_cast<nsISupports*>(
23 reinterpret_cast<char*>(aThis) + aEntries->offset);
24 NS_ADDREF(r);
25 *aInstancePtr = r;
26 return NS_OK;
29 ++aEntries;
30 } while (aEntries->iid);
32 *aInstancePtr = nullptr;
33 return NS_ERROR_NO_INTERFACE;
36 #ifndef XPCOM_GLUE_AVOID_NSPR
37 # ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
38 nsAutoOwningThread::nsAutoOwningThread() : mThread(PR_GetCurrentThread()) {}
40 void nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const {
41 if (MOZ_UNLIKELY(!IsCurrentThread())) {
42 // `msg` is a string literal by construction.
43 MOZ_CRASH_UNSAFE(msg);
47 bool nsAutoOwningThread::IsCurrentThread() const {
48 return mThread == PR_GetCurrentThread();
51 nsAutoOwningEventTarget::nsAutoOwningEventTarget()
52 : mTarget(GetCurrentSerialEventTarget()) {
53 NS_ADDREF(mTarget);
56 nsAutoOwningEventTarget::nsAutoOwningEventTarget(
57 const nsAutoOwningEventTarget& aOther)
58 : mTarget(aOther.mTarget) {
59 NS_ADDREF(mTarget);
62 nsAutoOwningEventTarget& nsAutoOwningEventTarget::operator=(
63 const nsAutoOwningEventTarget& aRhs) {
64 nsISerialEventTarget* previous = std::exchange(mTarget, aRhs.mTarget);
65 NS_ADDREF(mTarget);
66 NS_RELEASE(previous);
67 return *this;
70 nsAutoOwningEventTarget::~nsAutoOwningEventTarget() { NS_RELEASE(mTarget); }
72 void nsAutoOwningEventTarget ::AssertCurrentThreadOwnsMe(
73 const char* msg) const {
74 if (MOZ_UNLIKELY(!IsCurrentThread())) {
75 // `msg` is a string literal by construction.
76 MOZ_CRASH_UNSAFE(msg);
80 bool nsAutoOwningEventTarget::IsCurrentThread() const {
81 return mTarget->IsOnCurrentThread();
84 # endif
86 namespace mozilla::detail {
87 class ProxyDeleteVoidRunnable final : public CancelableRunnable {
88 public:
89 ProxyDeleteVoidRunnable(const char* aName, void* aPtr,
90 DeleteVoidFunction* aDeleteFunc)
91 : CancelableRunnable(aName), mPtr(aPtr), mDeleteFunc(aDeleteFunc) {}
93 NS_IMETHOD Run() override {
94 if (mPtr) {
95 mDeleteFunc(mPtr);
96 mPtr = nullptr;
98 return NS_OK;
101 // Mimics the behaviour in `ProxyRelease`, freeing the resource when
102 // cancelled.
103 nsresult Cancel() override { return Run(); }
105 # ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
106 NS_IMETHOD GetName(nsACString& aName) override {
107 if (mName) {
108 aName.Append(mName);
109 } else {
110 aName.AssignLiteral("ProxyDeleteVoidRunnable");
112 return NS_OK;
114 # endif
116 private:
117 ~ProxyDeleteVoidRunnable() {
118 if (mPtr) {
119 # ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
120 NS_WARNING(
121 nsPrintfCString(
122 "ProxyDeleteVoidRunnable for '%s' never run, leaking!", mName)
123 .get());
124 # else
125 NS_WARNING("ProxyDeleteVoidRunnable never run, leaking!");
126 # endif
130 void* mPtr;
131 DeleteVoidFunction* mDeleteFunc;
134 void ProxyDeleteVoid(const char* aName, nsISerialEventTarget* aTarget,
135 void* aPtr, DeleteVoidFunction* aDeleteFunc) {
136 MOZ_ASSERT(aName);
137 MOZ_ASSERT(aPtr);
138 MOZ_ASSERT(aDeleteFunc);
139 if (!aTarget) {
140 NS_WARNING(nsPrintfCString("no target for '%s', leaking!", aName).get());
141 return;
144 if (aTarget->IsOnCurrentThread()) {
145 aDeleteFunc(aPtr);
146 return;
148 nsresult rv = aTarget->Dispatch(
149 MakeAndAddRef<ProxyDeleteVoidRunnable>(aName, aPtr, aDeleteFunc),
150 NS_DISPATCH_NORMAL);
151 if (NS_FAILED(rv)) {
152 NS_WARNING(nsPrintfCString("failed to post '%s', leaking!", aName).get());
155 } // namespace mozilla::detail
156 #endif