- Timestamp:
- Nov 10, 2023 7:53:16 AM (18 months ago)
- svn:sync-xref-src-repo-rev:
- 160165
- Location:
- trunk/src/libs/xpcom18a4/xpcom/threads
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp
r102016 r102057 52 52 53 53 #include "nsEventQueueService.h" 54 #include "prmon.h"55 54 #include "nsIComponentManager.h" 56 55 #include "nsPIEventQueueChain.h" … … 58 57 #include "nsXPCOM.h" 59 58 59 #include <iprt/assert.h> 60 60 #include <VBox/log.h> 61 61 … … 64 64 nsEventQueueServiceImpl::nsEventQueueServiceImpl() 65 65 { 66 mEventQMonitor = PR_NewMonitor(); 66 mEventQMonitor = NIL_RTSEMFASTMUTEX; 67 int vrc = RTSemFastMutexCreate(&mEventQMonitor); 68 AssertRC(vrc); RT_NOREF(vrc); 67 69 } 68 70 … … 72 74 void* closure) 73 75 { 74 // 'aQueue' should be the eldest queue. 75 nsCOMPtr<nsPIEventQueueChain> pie(do_QueryInterface(aEldestQueue)); 76 nsCOMPtr<nsIEventQueue> q; 77 78 // stop accepting events for youngest to oldest 79 pie->GetYoungest(getter_AddRefs(q)); 80 while (q) { 81 q->StopAcceptingEvents(); 82 83 nsCOMPtr<nsPIEventQueueChain> pq(do_QueryInterface(q)); 84 pq->GetElder(getter_AddRefs(q)); 85 } 86 87 return PL_DHASH_REMOVE; 76 // 'aQueue' should be the eldest queue. 77 nsCOMPtr<nsPIEventQueueChain> pie(do_QueryInterface(aEldestQueue)); 78 nsCOMPtr<nsIEventQueue> q; 79 80 // stop accepting events for youngest to oldest 81 pie->GetYoungest(getter_AddRefs(q)); 82 while (q) 83 { 84 q->StopAcceptingEvents(); 85 86 nsCOMPtr<nsPIEventQueueChain> pq(do_QueryInterface(q)); 87 pq->GetElder(getter_AddRefs(q)); 88 } 89 90 return PL_DHASH_REMOVE; 88 91 } 89 92 90 93 nsEventQueueServiceImpl::~nsEventQueueServiceImpl() 91 94 { 92 // XXX make it so we only enum over this once 93 mEventQTable.Enumerate(hash_enum_remove_queues, nsnull); // call StopAcceptingEvents on everything and clear out the hashtable 94 95 PR_DestroyMonitor(mEventQMonitor); 95 // XXX make it so we only enum over this once 96 mEventQTable.Enumerate(hash_enum_remove_queues, nsnull); // call StopAcceptingEvents on everything and clear out the hashtable 97 98 int vrc = RTSemFastMutexDestroy(mEventQMonitor); 99 AssertRC(vrc); RT_NOREF(vrc); 100 mEventQMonitor = NIL_RTSEMFASTMUTEX; 96 101 } 97 102 … … 99 104 nsEventQueueServiceImpl::Init() 100 105 { 101 NS_ENSURE_TRUE(mEventQMonitor, NS_ERROR_OUT_OF_MEMORY); 102 103 // This will only be called once on the main thread, so it's safe to 104 // not enter the monitor here. 105 if (!mEventQTable.Init()) { 106 return NS_ERROR_OUT_OF_MEMORY; 107 } 108 109 // ensure that a main thread event queue exists! 110 RTTHREAD hMainThread; 111 nsresult rv = NS_GetMainThread(&hMainThread); 112 if (NS_SUCCEEDED(rv)) 113 rv = CreateEventQueue(hMainThread, PR_TRUE); 106 NS_ENSURE_TRUE(mEventQMonitor != NIL_RTSEMFASTMUTEX, NS_ERROR_OUT_OF_MEMORY); 107 108 // This will only be called once on the main thread, so it's safe to 109 // not enter the monitor here. 110 if (!mEventQTable.Init()) 111 return NS_ERROR_OUT_OF_MEMORY; 112 113 // ensure that a main thread event queue exists! 114 RTTHREAD hMainThread; 115 nsresult rv = NS_GetMainThread(&hMainThread); 116 if (NS_SUCCEEDED(rv)) 117 rv = CreateEventQueue(hMainThread, PR_TRUE); 114 118 115 119 return rv; … … 124 128 nsEventQueueServiceImpl::CreateThreadEventQueue() 125 129 { 126 return CreateEventQueue(RTThreadSelf(), PR_TRUE);130 return CreateEventQueue(RTThreadSelf(), PR_TRUE); 127 131 } 128 132 … … 130 134 nsEventQueueServiceImpl::CreateMonitoredThreadEventQueue() 131 135 { 132 return CreateEventQueue(RTThreadSelf(), PR_FALSE);136 return CreateEventQueue(RTThreadSelf(), PR_FALSE); 133 137 } 134 138 … … 137 141 nsIEventQueue **aResult) 138 142 { 139 nsresult rv;140 141 rv = CreateEventQueue(aThread, aNative); // addrefs142 if (NS_SUCCEEDED(rv))143 rv = GetThreadEventQueue(aThread, aResult); // addrefs144 145 return rv;143 nsresult rv; 144 145 rv = CreateEventQueue(aThread, aNative); // addrefs 146 if (NS_SUCCEEDED(rv)) 147 rv = GetThreadEventQueue(aThread, aResult); // addrefs 148 149 return rv; 146 150 } 147 151 … … 152 156 nsIEventQueue **aQueue) 153 157 { 154 nsresult rv;155 nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv);156 157 if (NS_SUCCEEDED(rv)) {158 rv = queue->InitFromPRThread(hThread, aNative);159 } 160 *aQueue = queue;161 NS_IF_ADDREF(*aQueue);162 return rv;158 nsresult rv; 159 nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv); 160 161 if (NS_SUCCEEDED(rv)) 162 rv = queue->InitFromPRThread(hThread, aNative); 163 164 *aQueue = queue; 165 NS_IF_ADDREF(*aQueue); 166 return rv; 163 167 } 164 168 … … 167 171 nsEventQueueServiceImpl::CreateEventQueue(RTTHREAD aThread, PRBool aNative) 168 172 { 169 nsresult rv = NS_OK; 170 /* Enter the lock that protects the EventQ hashtable... */ 171 PR_EnterMonitor(mEventQMonitor); 172 173 /* create only one event queue chain per thread... */ 174 if (!mEventQTable.GetWeak(aThread)) { 175 nsCOMPtr<nsIEventQueue> queue; 176 177 // we don't have one in the table 178 rv = MakeNewQueue(aThread, aNative, getter_AddRefs(queue)); // create new queue 179 mEventQTable.Put(aThread, queue); // add to the table (initial addref) 180 } 181 182 // Release the EventQ lock... 183 PR_ExitMonitor(mEventQMonitor); 184 return rv; 173 nsresult rv = NS_OK; 174 /* Enter the lock that protects the EventQ hashtable... */ 175 RTSemFastMutexRequest(mEventQMonitor); 176 177 /* create only one event queue chain per thread... */ 178 if (!mEventQTable.GetWeak(aThread)) 179 { 180 nsCOMPtr<nsIEventQueue> queue; 181 182 // we don't have one in the table 183 rv = MakeNewQueue(aThread, aNative, getter_AddRefs(queue)); // create new queue 184 mEventQTable.Put(aThread, queue); // add to the table (initial addref) 185 } 186 187 // Release the EventQ lock... 188 RTSemFastMutexRelease(mEventQMonitor); 189 return rv; 185 190 } 186 191 … … 189 194 nsEventQueueServiceImpl::DestroyThreadEventQueue(void) 190 195 { 191 nsresult rv = NS_OK; 192 193 /* Enter the lock that protects the EventQ hashtable... */ 194 PR_EnterMonitor(mEventQMonitor); 195 196 RTTHREAD hThread = RTThreadSelf(); 197 nsIEventQueue* queue = mEventQTable.GetWeak(hThread); 198 if (queue) { 199 queue->StopAcceptingEvents(); // tell the queue to stop accepting events 200 queue = nsnull; // Queue may die on the next line 201 mEventQTable.Remove(hThread); // remove nsIEventQueue from hash table (releases) 202 } 203 204 // Release the EventQ lock... 205 PR_ExitMonitor(mEventQMonitor); 206 return rv; 196 nsresult rv = NS_OK; 197 198 /* Enter the lock that protects the EventQ hashtable... */ 199 RTSemFastMutexRequest(mEventQMonitor); 200 201 RTTHREAD hThread = RTThreadSelf(); 202 nsIEventQueue* queue = mEventQTable.GetWeak(hThread); 203 if (queue) 204 { 205 queue->StopAcceptingEvents(); // tell the queue to stop accepting events 206 queue = nsnull; // Queue may die on the next line 207 mEventQTable.Remove(hThread); // remove nsIEventQueue from hash table (releases) 208 } 209 210 // Release the EventQ lock... 211 RTSemFastMutexRelease(mEventQMonitor); 212 return rv; 207 213 } 208 214 … … 210 216 nsEventQueueServiceImpl::CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult) 211 217 { 212 // Create our thread queue using the component manager 213 nsresult rv; 214 nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv); 215 if (NS_FAILED(rv)) return rv; 216 217 rv = queue->InitFromPLQueue(aPLEventQueue); 218 if (NS_FAILED(rv)) return rv; 219 220 *aResult = queue; 221 NS_IF_ADDREF(*aResult); 222 return NS_OK; 218 // Create our thread queue using the component manager 219 nsresult rv; 220 nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv); 221 if (NS_FAILED(rv)) 222 return rv; 223 224 rv = queue->InitFromPLQueue(aPLEventQueue); 225 if (NS_FAILED(rv)) 226 return rv; 227 228 *aResult = queue; 229 NS_IF_ADDREF(*aResult); 230 return NS_OK; 223 231 } 224 232 … … 228 236 nsresult nsEventQueueServiceImpl::GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult) 229 237 { 230 nsCOMPtr<nsIEventQueue> answer; 231 232 if (queue) { 233 nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue)); 234 if (ourChain) 235 ourChain->GetYoungestActive(getter_AddRefs(answer)); 236 else 237 answer = queue; 238 } 239 240 *aResult = answer; 241 NS_IF_ADDREF(*aResult); 242 return NS_OK; 238 nsCOMPtr<nsIEventQueue> answer; 239 240 if (queue) 241 { 242 nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue)); 243 if (ourChain) 244 ourChain->GetYoungestActive(getter_AddRefs(answer)); 245 else 246 answer = queue; 247 } 248 249 *aResult = answer; 250 NS_IF_ADDREF(*aResult); 251 return NS_OK; 243 252 } 244 253 … … 249 258 nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue) 250 259 { 251 nsresult rv = NS_OK; 252 RTTHREAD hThread = RTThreadSelf(); 253 PRBool native = PR_TRUE; // native by default as per old comment 254 255 256 NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param"); 257 258 /* Enter the lock that protects the EventQ hashtable... */ 259 PR_EnterMonitor(mEventQMonitor); 260 261 nsIEventQueue* queue = mEventQTable.GetWeak(hThread); 262 263 NS_ASSERTION(queue, "pushed event queue on top of nothing"); 264 265 if (queue) { // find out what kind of queue our relatives are 266 nsCOMPtr<nsIEventQueue> youngQueue; 267 GetYoungestEventQueue(queue, getter_AddRefs(youngQueue)); 268 if (youngQueue) { 269 youngQueue->IsQueueNative(&native); 270 } 271 } 272 273 nsIEventQueue* newQueue = nsnull; 274 MakeNewQueue(hThread, native, &newQueue); // create new queue; addrefs 275 276 if (!queue) { 277 // shouldn't happen. as a fallback, we guess you wanted a native queue 278 mEventQTable.Put(hThread, newQueue); 279 } 280 281 // append to the event queue chain 282 nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue)); // QI the queue in the hash table 283 if (ourChain) 284 ourChain->AppendQueue(newQueue); // append new queue to it 285 286 *aNewQueue = newQueue; 260 nsresult rv = NS_OK; 261 RTTHREAD hThread = RTThreadSelf(); 262 PRBool native = PR_TRUE; // native by default as per old comment 263 264 NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param"); 265 266 /* Enter the lock that protects the EventQ hashtable... */ 267 RTSemFastMutexRequest(mEventQMonitor); 268 269 nsIEventQueue* queue = mEventQTable.GetWeak(hThread); 270 271 NS_ASSERTION(queue, "pushed event queue on top of nothing"); 272 273 if (queue) 274 { 275 // find out what kind of queue our relatives are 276 nsCOMPtr<nsIEventQueue> youngQueue; 277 GetYoungestEventQueue(queue, getter_AddRefs(youngQueue)); 278 if (youngQueue) 279 youngQueue->IsQueueNative(&native); 280 } 281 282 nsIEventQueue* newQueue = nsnull; 283 MakeNewQueue(hThread, native, &newQueue); // create new queue; addrefs 284 285 if (!queue) 286 { 287 // shouldn't happen. as a fallback, we guess you wanted a native queue 288 mEventQTable.Put(hThread, newQueue); 289 } 290 291 // append to the event queue chain 292 nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue)); // QI the queue in the hash table 293 if (ourChain) 294 ourChain->AppendQueue(newQueue); // append new queue to it 295 296 *aNewQueue = newQueue; 287 297 288 298 #ifdef LOG_ENABLED 289 PLEventQueue *equeue;290 (*aNewQueue)->GetPLEventQueue(&equeue);291 Log(("EventQueue: Service push queue [queue=%lx]",(long)equeue));299 PLEventQueue *equeue; 300 (*aNewQueue)->GetPLEventQueue(&equeue); 301 Log(("EventQueue: Service push queue [queue=%lx]",(long)equeue)); 292 302 #endif 293 303 294 // Release the EventQ lock...295 PR_ExitMonitor(mEventQMonitor);296 return rv;304 // Release the EventQ lock... 305 RTSemFastMutexRelease(mEventQMonitor); 306 return rv; 297 307 } 298 308 … … 301 311 nsEventQueueServiceImpl::PopThreadEventQueue(nsIEventQueue *aQueue) 302 312 { 303 RTTHREAD hThread = RTThreadSelf();304 305 /* Enter the lock that protects the EventQ hashtable... */306 PR_EnterMonitor(mEventQMonitor);307 308 nsCOMPtr<nsIEventQueue> eldestQueue;309 mEventQTable.Get(hThread, getter_AddRefs(eldestQueue));310 311 // If we are popping the eldest queue, remove its mEventQTable entry.312 if (aQueue == eldestQueue)313 mEventQTable.Remove(hThread);314 315 // Exit the monitor before processing pending events to avoid deadlock.316 // Our reference from the eldestQueue nsCOMPtr will keep that object alive.317 // Since it is thread-private, no one else can race with us here.318 PR_ExitMonitor(mEventQMonitor);319 if (!eldestQueue)320 return NS_ERROR_FAILURE;313 RTTHREAD hThread = RTThreadSelf(); 314 315 /* Enter the lock that protects the EventQ hashtable... */ 316 RTSemFastMutexRequest(mEventQMonitor); 317 318 nsCOMPtr<nsIEventQueue> eldestQueue; 319 mEventQTable.Get(hThread, getter_AddRefs(eldestQueue)); 320 321 // If we are popping the eldest queue, remove its mEventQTable entry. 322 if (aQueue == eldestQueue) 323 mEventQTable.Remove(hThread); 324 325 // Exit the monitor before processing pending events to avoid deadlock. 326 // Our reference from the eldestQueue nsCOMPtr will keep that object alive. 327 // Since it is thread-private, no one else can race with us here. 328 RTSemFastMutexRelease(mEventQMonitor); 329 if (!eldestQueue) 330 return NS_ERROR_FAILURE; 321 331 322 332 #ifdef LOG_ENABLED 323 PLEventQueue *equeue;324 aQueue->GetPLEventQueue(&equeue);325 Log(("EventQueue: Service pop queue [queue=%lx]",(long)equeue));333 PLEventQueue *equeue; 334 aQueue->GetPLEventQueue(&equeue); 335 Log(("EventQueue: Service pop queue [queue=%lx]",(long)equeue)); 326 336 #endif 327 aQueue->StopAcceptingEvents();328 aQueue->ProcessPendingEvents(); // make sure we don't orphan any events329 330 return NS_OK;337 aQueue->StopAcceptingEvents(); 338 aQueue->ProcessPendingEvents(); // make sure we don't orphan any events 339 340 return NS_OK; 331 341 } 332 342 … … 334 344 nsEventQueueServiceImpl::GetThreadEventQueue(RTTHREAD aThread, nsIEventQueue** aResult) 335 345 { 336 /* Parameter validation... */ 337 if (NULL == aResult) return NS_ERROR_NULL_POINTER; 338 339 RTTHREAD keyThread = aThread; 340 341 if (keyThread == NS_CURRENT_THREAD) 342 { 343 keyThread = RTThreadSelf(); 344 } 345 else if (keyThread == NS_UI_THREAD) 346 { 347 // Get the primordial thread 348 nsresult rv = NS_GetMainThread(&keyThread); 349 if (NS_FAILED(rv)) return rv; 350 } 351 352 /* Enter the lock that protects the EventQ hashtable... */ 353 PR_EnterMonitor(mEventQMonitor); 354 355 nsCOMPtr<nsIEventQueue> queue; 356 mEventQTable.Get(keyThread, getter_AddRefs(queue)); 357 358 PR_ExitMonitor(mEventQMonitor); 359 360 if (queue) { 361 GetYoungestEventQueue(queue, aResult); // get the youngest active queue 362 } else { 363 *aResult = nsnull; 364 } 365 // XXX: Need error code for requesting an event queue when none exists... 366 if (!*aResult) { 367 return NS_ERROR_NOT_AVAILABLE; 368 } 369 return NS_OK; 346 /* Parameter validation... */ 347 AssertReturn(aResult != NULL, NS_ERROR_NULL_POINTER); 348 349 RTTHREAD keyThread = aThread; 350 351 if (keyThread == NS_CURRENT_THREAD) 352 keyThread = RTThreadSelf(); 353 else if (keyThread == NS_UI_THREAD) 354 { 355 // Get the primordial thread 356 nsresult rv = NS_GetMainThread(&keyThread); 357 if (NS_FAILED(rv)) 358 return rv; 359 } 360 361 /* Enter the lock that protects the EventQ hashtable... */ 362 RTSemFastMutexRequest(mEventQMonitor); 363 364 nsCOMPtr<nsIEventQueue> queue; 365 mEventQTable.Get(keyThread, getter_AddRefs(queue)); 366 367 RTSemFastMutexRelease(mEventQMonitor); 368 369 if (queue) 370 GetYoungestEventQueue(queue, aResult); // get the youngest active queue 371 else 372 *aResult = nsnull; 373 374 // XXX: Need error code for requesting an event queue when none exists... 375 if (!*aResult) 376 return NS_ERROR_NOT_AVAILABLE; 377 378 return NS_OK; 370 379 } 371 380 … … 374 383 nsEventQueueServiceImpl::ResolveEventQueue(nsIEventQueue* queueOrConstant, nsIEventQueue* *resultQueue) 375 384 { 376 if (queueOrConstant == NS_CURRENT_EVENTQ) { 377 return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue); 378 } 379 else if (queueOrConstant == NS_UI_THREAD_EVENTQ) { 380 return GetThreadEventQueue(NS_UI_THREAD, resultQueue); 381 } 382 383 *resultQueue = queueOrConstant; 384 NS_ADDREF(*resultQueue); 385 return NS_OK; 385 if (queueOrConstant == NS_CURRENT_EVENTQ) 386 return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue); 387 else if (queueOrConstant == NS_UI_THREAD_EVENTQ) 388 return GetThreadEventQueue(NS_UI_THREAD, resultQueue); 389 390 *resultQueue = queueOrConstant; 391 NS_ADDREF(*resultQueue); 392 return NS_OK; 386 393 } 387 394 … … 390 397 nsIEventQueue* *_retval) 391 398 { 392 nsresult rv; 393 394 // barf if someone gave us a zero pointer 395 // 396 if (!_retval) { 397 return NS_ERROR_NULL_POINTER; 398 } 399 400 // try and get the requested event queue, returning NS_ERROR_FAILURE if there 401 // is a problem. GetThreadEventQueue() does the AddRef() for us. 402 // 403 switch (aQueue) { 404 case CURRENT_THREAD_EVENT_QUEUE: 405 rv = GetThreadEventQueue(NS_CURRENT_THREAD, _retval); 406 if (NS_FAILED(rv)) { 407 return NS_ERROR_FAILURE; 408 } 409 break; 410 411 case UI_THREAD_EVENT_QUEUE: 412 rv = GetThreadEventQueue(NS_UI_THREAD, _retval); 413 if (NS_FAILED(rv)) { 414 return NS_ERROR_FAILURE; 415 } 416 break; 417 418 // somebody handed us a bogus constant 419 // 420 default: 421 return NS_ERROR_ILLEGAL_VALUE; 422 } 423 424 return NS_OK; 425 } 426 399 AssertReturn(_retval, NS_ERROR_NULL_POINTER); 400 401 // try and get the requested event queue, returning NS_ERROR_FAILURE if there 402 // is a problem. GetThreadEventQueue() does the AddRef() for us. 403 switch (aQueue) 404 { 405 case CURRENT_THREAD_EVENT_QUEUE: 406 { 407 nsresult rv = GetThreadEventQueue(NS_CURRENT_THREAD, _retval); 408 if (NS_FAILED(rv)) 409 return NS_ERROR_FAILURE; 410 break; 411 } 412 case UI_THREAD_EVENT_QUEUE: 413 { 414 nsresult rv = GetThreadEventQueue(NS_UI_THREAD, _retval); 415 if (NS_FAILED(rv)) 416 return NS_ERROR_FAILURE; 417 break; 418 } 419 /* somebody handed us a bogus constant */ 420 default: 421 return NS_ERROR_ILLEGAL_VALUE; 422 } 423 424 return NS_OK; 425 } 426 -
trunk/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h
r102016 r102057 44 44 #include "nsIEventQueue.h" 45 45 46 #include <iprt/semaphore.h> 47 46 48 //////////////////////////////////////////////////////////////////////////////// 47 49 … … 70 72 71 73 nsInterfaceHashtable<nsVoidPtrHashKey, nsIEventQueue> mEventQTable; 72 PRMonitor *mEventQMonitor;74 RTSEMFASTMUTEX mEventQMonitor; 73 75 }; 74 76
Note:
See TracChangeset
for help on using the changeset viewer.