- Timestamp:
- Jun 4, 2007 7:19:11 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp
r2971 r3036 247 247 return count; 248 248 } 249 250 // this gets called after calling AddRef() on an instance passed to the 251 // client over IPC in order to have a count of IPC client-related references 252 // separately from the overall reference count 253 NS_IMETHODIMP_(nsrefcnt) AddRefIPC(void) 254 { 255 NS_PRECONDITION(PRInt32(mRefCntIPC) >= 0, "illegal refcnt"); 256 nsrefcnt count; 257 count = PR_AtomicIncrement((PRInt32*)&mRefCntIPC); 258 return count; 259 } 260 261 // this gets called before calling Release() when DCON_OP_RELEASE is 262 // received from the IPC client 263 NS_IMETHODIMP_(nsrefcnt) ReleaseIPC(void) 264 { 265 NS_PRECONDITION(0 != mRefCntIPC, "dup release"); 266 nsrefcnt count; 267 count = PR_AtomicDecrement((PRInt32 *)&mRefCntIPC); 268 return count; 269 } 249 270 250 271 private: 251 272 nsAutoRefCnt mRefCnt; 273 nsAutoRefCnt mRefCntIPC; 252 274 PRUint32 mPeer; // peer process "owning" this instance 253 275 nsCOMPtr<nsIInterfaceInfo> mIInfo; … … 259 281 { 260 282 for (PRInt32 i=0; i<wrappers.Count(); ++i) 283 { 284 ((DConnectInstance *) wrappers[i])->ReleaseIPC(); 261 285 ((DConnectInstance *) wrappers[i])->Release(); 286 } 262 287 } 263 288 … … 1106 1131 1107 1132 // wrapper remains referenced when passing it to the client 1108 // (will be released upon DCON_OP_RELEASE) 1133 // (will be released upon DCON_OP_RELEASE). increase the 1134 // second, IPC-only, reference counter 1135 wrapper->AddRefIPC(); 1109 1136 1110 1137 // send address of the instance wrapper, and set the low bit … … 1373 1400 1374 1401 // wrapper remains referenced when passing it to the client 1375 // (will be released upon DCON_OP_RELEASE) 1376 1402 // (will be released upon DCON_OP_RELEASE). increase the 1403 // second, IPC-only, reference counter 1404 wrapper->AddRefIPC(); 1405 1377 1406 // send address of the instance wrapper, and set the low bit 1378 1407 // to indicate that this is an instance wrapper. … … 2674 2703 if (args && args->clientID == aData->Peer()) 2675 2704 { 2676 // ignore the reference counter: the client is officially dead 2677 args->that->DeleteInstance(aData, PR_TRUE /* locked */); 2705 // add a fake reference to hold the wrapper alive 2706 nsrefcnt count = aData->AddRef(); 2707 2708 // release all IPC references for this wrapper, the client is now 2709 // officially dead (and thus cannot call AddRefIPC in the middle) 2710 nsrefcnt countIPC = aData->AddRefIPC(); 2711 countIPC = aData->ReleaseIPC(); 2712 2713 LOG(("ipcDConnectService::PruneInstanceMapForPeer: " 2714 "instance=%p: %d IPC refs to release (total refcnt=%d)\n", 2715 aData, countIPC, count)); 2716 2717 while (countIPC) 2718 { 2719 countIPC = aData->ReleaseIPC(); 2720 aData->Release(); 2721 } 2722 2678 2723 // collect the instance for future destruction 2679 2724 if (!args->wrappers.AppendElement(aData)) … … 2717 2762 } 2718 2763 2719 // destruct all instances outside the lock because it will release 2720 // the real objects which may need to make asynchronous use our service 2764 LOG(("ipcDConnectService::OnClientStateChange: " 2765 "%d lost instances (should be 0 unless the peer has " 2766 "crashed)\n", wrappers.Count())); 2767 2768 // release all fake references we've added in PruneInstanceMapForPeer(). 2769 // this may call wrapper destructors so it's important to do that 2770 // outside the lock because destructors will release the real 2771 // objects which may need to make asynchronous use our service 2721 2772 for (PRInt32 i = 0; i < wrappers.Count(); ++i) 2722 delete ((DConnectInstance *) wrappers[i]);2773 ((DConnectInstance *) wrappers[i])->Release(); 2723 2774 } 2724 2775 } … … 2876 2927 2877 2928 // wrapper remains referenced when passing it to the client 2878 // (will be released upon DCON_OP_RELEASE) 2929 // (will be released upon DCON_OP_RELEASE). increase the 2930 // second, IPC-only, reference counter 2931 wrapper->AddRefIPC(); 2879 2932 } 2880 2933 } … … 2947 3000 if (mInstanceSet.Contains(wrapper)) 2948 3001 { 3002 // add a fake reference to hold the wrapper alive 2949 3003 nsrefcnt count = wrapper->AddRef(); 3004 3005 // release references 3006 nsrefcnt countIPC = wrapper->ReleaseIPC(); 2950 3007 count = wrapper->Release(); 3008 3009 NS_ASSERTION(count > 0, "unbalanced AddRef()/Release()"); 3010 2951 3011 if (count == 1) 2952 3012 { 3013 NS_ASSERTION(countIPC == 0, "unbalanced AddRefIPC()/ReleaseIPC()"); 3014 2953 3015 // we are the last one who holds a (fake) reference, remove the 2954 3016 // instace from instance maps while still under the lock 2955 3017 DeleteInstance(wrapper, PR_TRUE /* locked */); 3018 2956 3019 // leave the lock before calling the destructor because it will release 2957 3020 // the real object which may need to make asynchronous use our service 2958 3021 lock.unlock(); 2959 3022 delete wrapper; 3023 } 3024 else 3025 { 3026 // release the fake reference 3027 wrapper->Release(); 2960 3028 } 2961 3029 }
Note:
See TracChangeset
for help on using the changeset viewer.