1 // ==++== 2 // 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // 5 // ==--== 6 /*============================================================ 7 ** 8 ** File: TrackingServices.cs 9 ** 10 ** 11 ** Purpose: Defines the services for tracking lifetime and other 12 ** operations on objects. 13 ** 14 ** 15 ===========================================================*/ 16 namespace System.Runtime.Remoting.Services { 17 using System.Security.Permissions; 18 using System; 19 using System.Threading; 20 using System.Globalization; 21 using System.Diagnostics.Contracts; 22 using System.Diagnostics.CodeAnalysis; 23 24 [System.Runtime.InteropServices.ComVisible(true)] 25 public interface ITrackingHandler 26 { 27 // Notify a handler that an object has been marshaled 28 [System.Security.SecurityCritical] // auto-generated_required MarshaledObject(Object obj, ObjRef or)29 void MarshaledObject(Object obj, ObjRef or); 30 31 // Notify a handler that an object has been unmarshaled 32 [System.Security.SecurityCritical] // auto-generated_required UnmarshaledObject(Object obj, ObjRef or)33 void UnmarshaledObject(Object obj, ObjRef or); 34 35 // Notify a handler that an object has been disconnected 36 [System.Security.SecurityCritical] // auto-generated_required DisconnectedObject(Object obj)37 void DisconnectedObject(Object obj); 38 } 39 40 41 [System.Security.SecurityCritical] // auto-generated_required 42 [System.Runtime.InteropServices.ComVisible(true)] 43 public class TrackingServices 44 { 45 // Private member variables 46 private static volatile ITrackingHandler[] _Handlers = new ITrackingHandler[0]; // Array of registered tracking handlers 47 private static volatile int _Size = 0; // Number of elements in the array 48 49 private static Object s_TrackingServicesSyncObject = null; 50 51 private static Object TrackingServicesSyncObject 52 { 53 get 54 { 55 if (s_TrackingServicesSyncObject == null) 56 { 57 Object o = new Object(); 58 Interlocked.CompareExchange(ref s_TrackingServicesSyncObject, o, null); 59 } 60 return s_TrackingServicesSyncObject; 61 } 62 } 63 64 [System.Security.SecurityCritical] // auto-generated RegisterTrackingHandler(ITrackingHandler handler)65 public static void RegisterTrackingHandler(ITrackingHandler handler) 66 { 67 // Validate arguments 68 if (null == handler) 69 { 70 throw new ArgumentNullException("handler"); 71 } 72 Contract.EndContractBlock(); 73 74 lock (TrackingServicesSyncObject) 75 { 76 // Check to make sure that the handler has not been registered 77 if(-1 == Match(handler)) 78 { 79 // Allocate a new array if necessary 80 if((null == _Handlers) || (_Size == _Handlers.Length)) 81 { 82 ITrackingHandler[] temp = new ITrackingHandler[_Size*2+4]; 83 if(null != _Handlers) 84 { 85 Array.Copy(_Handlers, temp, _Size); 86 } 87 _Handlers = temp; 88 } 89 90 Volatile.Write(ref _Handlers[_Size++], handler); 91 } 92 else 93 { 94 throw new RemotingException(Environment.GetResourceString("Remoting_TrackingHandlerAlreadyRegistered", "handler")); 95 } 96 } 97 } 98 99 [System.Security.SecurityCritical] // auto-generated UnregisterTrackingHandler(ITrackingHandler handler)100 public static void UnregisterTrackingHandler(ITrackingHandler handler) 101 { 102 // Validate arguments 103 if (null == handler) 104 { 105 throw new ArgumentNullException("handler"); 106 } 107 Contract.EndContractBlock(); 108 109 lock (TrackingServicesSyncObject) 110 { 111 // Check to make sure that the channel has been registered 112 int matchingIdx = Match(handler); 113 if(-1 == matchingIdx) 114 { 115 throw new RemotingException(Environment.GetResourceString("Remoting_HandlerNotRegistered", handler)); 116 } 117 118 // Delete the entry by copying the remaining entries 119 Array.Copy(_Handlers, matchingIdx+1, _Handlers, matchingIdx, _Size-matchingIdx-1); 120 _Size--; 121 } 122 } 123 124 public static ITrackingHandler[] RegisteredHandlers 125 { 126 [System.Security.SecurityCritical] // auto-generated 127 get 128 { 129 lock(TrackingServicesSyncObject) 130 { 131 if(0 == _Size) 132 { 133 return new ITrackingHandler[0]; 134 } 135 else 136 { 137 // Copy the array of registered handlers into a new array 138 // and return 139 ITrackingHandler[] temp = new ITrackingHandler[_Size]; 140 for(int i = 0; i < _Size; i++) 141 { 142 temp[i] = _Handlers[i]; 143 } 144 return temp; 145 } 146 } 147 } 148 } 149 150 // Notify all the handlers that an object has been marshaled 151 [System.Security.SecurityCritical] // auto-generated MarshaledObject(Object obj, ObjRef or)152 internal static void MarshaledObject(Object obj, ObjRef or) 153 { 154 try{ 155 ITrackingHandler[] temp = _Handlers; 156 for(int i = 0; i < _Size; i++) 157 { 158 Volatile.Read(ref temp[i]).MarshaledObject(obj, or); 159 } 160 } 161 catch {} 162 } 163 164 // Notify all the handlers that an object has been unmarshaled 165 [System.Security.SecurityCritical] // auto-generated UnmarshaledObject(Object obj, ObjRef or)166 internal static void UnmarshaledObject(Object obj, ObjRef or) 167 { 168 try{ 169 ITrackingHandler[] temp = _Handlers; 170 for(int i = 0; i < _Size; i++) 171 { 172 Volatile.Read(ref temp[i]).UnmarshaledObject(obj, or); 173 } 174 } 175 catch {} 176 } 177 178 // Notify all the handlers that an object has been disconnected 179 [System.Security.SecurityCritical] // auto-generated DisconnectedObject(Object obj)180 internal static void DisconnectedObject(Object obj) 181 { 182 try{ 183 ITrackingHandler[] temp = _Handlers; 184 for(int i = 0; i < _Size; i++) 185 { 186 Volatile.Read(ref temp[i]).DisconnectedObject(obj); 187 } 188 } 189 catch {} 190 } 191 192 [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")] Match(ITrackingHandler handler)193 private static int Match(ITrackingHandler handler) 194 { 195 int idx = -1; 196 197 for(int i = 0; i < _Size; i++) 198 { 199 if(_Handlers[i] == handler) 200 { 201 idx = i; 202 break; 203 } 204 } 205 206 return idx; 207 } 208 } 209 210 } // namespace 211