Changeset 2499 in vbox
- Timestamp:
- May 4, 2007 4:49:18 PM (18 years ago)
- Location:
- trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp
r2440 r2499 239 239 nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance()); 240 240 if (dConnect) 241 241 dConnect->DeleteInstance(this); 242 242 else 243 243 NS_NOTREACHED("ipcDConnectService has gone before DConnectInstance"); 244 244 delete this; 245 245 return 0; … … 2223 2223 // disregarding the reference counter 2224 2224 2225 #ifdef IPC_LOGGING 2226 const char *name; 2227 aData->InterfaceInfo()->GetNameShared(&name); 2228 LOG(("ipcDConnectService: WARNING: deleting unreleased " 2229 "instance=%p iface=%p {%s}\n", aData, aData->RealInstance(), name)); 2230 #endif 2231 2225 2232 delete aData; 2226 2233 return PL_DHASH_NEXT; … … 2424 2431 2425 2432 void 2426 ipcDConnectService::DeleteInstance(DConnectInstance *wrapper) 2427 { 2433 ipcDConnectService::DeleteInstance(DConnectInstance *wrapper, 2434 PRBool locked /* = PR_FALSE */) 2435 { 2436 if (!locked) 2437 PR_Lock(mLock); 2438 2428 2439 #ifdef IPC_LOGGING 2429 2440 const char *name; … … 2433 2444 #endif 2434 2445 2435 { 2436 nsAutoLock lock (mLock); 2437 2438 mInstances.Remove(wrapper->GetKey()); 2439 mInstanceSet.Remove(wrapper); 2440 } 2446 mInstances.Remove(wrapper->GetKey()); 2447 mInstanceSet.Remove(wrapper); 2448 2449 if (!locked) 2450 PR_Unlock(mLock); 2441 2451 } 2442 2452 … … 2648 2658 struct PruneInstanceMapForPeerArgs 2649 2659 { 2660 ipcDConnectService *that; 2650 2661 PRUint32 clientID; 2651 DConnectInstanceMap &instances; 2652 DConnectInstanceSet &instanceSet; 2662 nsVoidArray &wrappers; 2653 2663 }; 2654 2664 … … 2663 2673 if (args && args->clientID == aData->Peer()) 2664 2674 { 2665 #ifdef IPC_LOGGING 2666 const char *name; 2667 aData->InterfaceInfo()->GetNameShared(&name); 2668 LOG(("PruneInstanceMapForClient(): instance=%p iface=%p {%s} peer=%d\n", 2669 aData, aData->RealInstance(), name, args->clientID)); 2670 #endif 2671 args->instances.Remove(aKey); 2672 args->instanceSet.Remove(aData); 2673 /* ignore the reference counter: the client is officially dead */ 2674 delete aData; 2675 // ignore the reference counter: the client is officially dead 2676 args->that->DeleteInstance(aData, PR_TRUE /* locked */); 2677 // collect the instance for future destruction 2678 if (!args->wrappers.AppendElement(aData)) 2679 { 2680 NS_NOTREACHED("Not enough memory"); 2681 // bad but what to do 2682 delete aData; 2683 } 2675 2684 } 2676 2685 return PL_DHASH_NEXT; … … 2697 2706 "pruning all instances created for peer %d...\n", aClientID)); 2698 2707 2699 nsAutoLock lock (mLock); 2700 2701 // make sure we have released all instances 2702 PruneInstanceMapForPeerArgs args = { aClientID, mInstances, mInstanceSet }; 2703 mInstances.EnumerateRead(PruneInstanceMapForPeer, (void *)&args); 2708 nsVoidArray wrappers; 2709 2710 { 2711 nsAutoLock lock (mLock); 2712 2713 // make sure we have removed all instances from instance maps 2714 PruneInstanceMapForPeerArgs args = { this, aClientID, wrappers }; 2715 mInstances.EnumerateRead(PruneInstanceMapForPeer, (void *)&args); 2716 } 2717 2718 // destruct all instances outside the lock because it will release 2719 // the real objects which may need to make asynchronous use our service 2720 for (PRInt32 i = 0; i < wrappers.Count(); ++i) 2721 delete ((DConnectInstance *) wrappers[i]); 2704 2722 } 2705 2723 } … … 2921 2939 peer, release->instance)); 2922 2940 2941 DConnectInstance *wrapper = release->instance; 2942 2943 nsAutoLock lock (mLock); 2944 2923 2945 // make sure we've been sent a valid wrapper 2924 if (CheckInstanceAndAddRef(release->instance)) 2925 { 2926 // release twice: once to balance CheckInstanceAndAddRef() and once 2927 // to satisfy the RELEASE request (the instance is no more needed by 2928 // this peer) 2929 release->instance->Release(); 2930 release->instance->Release(); 2946 if (mInstanceSet.Contains(wrapper)) 2947 { 2948 nsrefcnt count = wrapper->AddRef(); 2949 count = wrapper->Release(); 2950 if (count == 1) 2951 { 2952 // we are the last one who holds a (fake) reference, remove the 2953 // instace from instance maps while still under the lock 2954 DeleteInstance(wrapper, PR_TRUE /* locked */); 2955 // leave the lock before calling the destructor because it will release 2956 // the real object which may need to make asynchronous use our service 2957 lock.unlock(); 2958 delete wrapper; 2959 } 2931 2960 } 2932 2961 else 2933 2962 { 2934 NS_NOTREACHED("instance wrapper not found"); 2963 // it is possible that the client disconnection event handler has released 2964 // all client instances before the RELEASE message sent by the client gets 2965 // processed here. Just give a warning 2966 LOG(("ipcDConnectService::OnRelease: WARNING: instance wrapper not found")); 2935 2967 } 2936 2968 } -
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h
r2093 r2499 233 233 234 234 // public only for DConnectInstance::Release() 235 NS_HIDDEN_(void) DeleteInstance(DConnectInstance * );235 NS_HIDDEN_(void) DeleteInstance(DConnectInstance *, PRBool locked = PR_FALSE); 236 236 // public only for DConnectStub::CallMethod() 237 237 NS_HIDDEN_(PRBool) CheckInstanceAndAddRef(DConnectInstance *);
Note:
See TracChangeset
for help on using the changeset viewer.