/// <summary> /// Constructor. /// </summary> public SuperPoolClients() { #if Matrix_Diagnostics InstanceMonitor = new InstanceMonitor(this); #endif _proxyTypeManager = new ProxyTypeManager(); }
object IProxyTypeSink.ReceivePropertyGet(int methodId, Type returnType) { SuperPoolProxyCall pendingCall = null; if (_pendingThreadsCalls.TryGetValue(Thread.CurrentThread.ManagedThreadId, out pendingCall) == false) { #if Matrix_Diagnostics InstanceMonitor.OperationError("Failed to find corresponding thread proxy call information."); #endif return(null); } pendingCall.Parameters = null; pendingCall.ReturnType = returnType; ProxyTypeBuilder builder = ProxyTypeBuilder; if (builder == null) { #if Matrix_Diagnostics InstanceMonitor.OperationError("Failed to find proxy type builder."); #endif return(ProxyTypeManager.GetTypeDefaultValue(returnType)); } pendingCall.MethodInfo = builder.GetMethodInfoById(methodId); if (pendingCall.MethodInfo == null) { #if Matrix_Diagnostics InstanceMonitor.OperationError("Failed to find method [" + methodId + "] info."); #endif return(ProxyTypeManager.GetTypeDefaultValue(returnType)); } return(pendingCall.Sender.ProcessCall(pendingCall)); }
/// <summary> /// Client source has raised an event, process it. /// </summary> internal object ProcessEventRaised(ClientEventsHandler client, ClientEventsHandler.EventHandlingInformation eventSubscriptionInfo, Type returnType, object[] parameters) { if (string.IsNullOrEmpty(eventSubscriptionInfo.GeneratedMethodInfo.EventName)) { // Establish the name of the event. eventSubscriptionInfo.GeneratedMethodInfo.EventName = GeneralHelper.GetEventMethodExtendedName(eventSubscriptionInfo.EventInfo, false); } EventSubscriptionInfo eventSubscription = null; if (string.IsNullOrEmpty(eventSubscriptionInfo.GeneratedMethodInfo.EventName) == false && _eventSubscriptions.TryGetValue(eventSubscriptionInfo.GeneratedMethodInfo.EventName, out eventSubscription)) {// OK, to perform the calls. // Process specific subscribers foreach (KeyValuePair <ClientId, EventSubscriptionInfo.ClientEventSubscriptionInfo> pair in eventSubscription.GetReceivers(client.Client.Id, true)) { foreach (KeyValuePair <MethodInfo, int> subPair in pair.Value.Data) { for (int i = 0; i < subPair.Value; i++) { // May need to raise multiple times. if (client.Client.Id != pair.Key) { // Filter out subscriptions by the one that raised it. ProcessEventCall(client.Client.Id, pair.Key, subPair.Key, parameters); } } } } // Process subscribe to all. foreach (KeyValuePair <ClientId, EventSubscriptionInfo.ClientEventSubscriptionInfo> pair in eventSubscription.GetReceivers(client.Client.Id, false)) { foreach (KeyValuePair <MethodInfo, int> subPair in pair.Value.Data) { for (int i = 0; i < subPair.Value; i++) { // May need to raise multiple times. if (client.Client.Id != pair.Key) { // Filter out subscriptions by the one that raised it. ProcessEventCall(client.Client.Id, pair.Key, subPair.Key, parameters); } } } } } else {// No subscription(s) for this event. #if Matrix_Diagnostics InstanceMonitor.Info(string.Format("Event raised [{0}] had no subscribers.", eventSubscriptionInfo.GeneratedMethodInfo.EventName), TracerItem.PriorityEnum.Trivial); #endif } // Return a default value. return(ProxyTypeManager.GetTypeDefaultValue(returnType)); }
public virtual void Dispose() { ProxyTypeManager manager = _proxyTypeManager; if (manager != null) { manager.Dispose(); _proxyTypeManager = null; } IMessageBus messageBus = _messageBus; _messageBus = null; if (messageBus != null) { messageBus.ClientAddedEvent -= new MessageBusClientUpdateDelegate(_messageBus_ClientAddedEvent); messageBus.ClientRemovedEvent -= new MessageBusClientRemovedDelegate(_messageBus_ClientRemovedEvent); messageBus.ClientUpdateEvent -= new MessageBusClientUpdateDelegate(_messageBus_ClientUpdateEvent); messageBus.Dispose(); } }
/// <summary> /// An event (with return value) was raised by our source. /// </summary> public object ReceiveDynamicMethodCallAndReturn(int methodId, Type returnType, object[] parameters) { EventHandlingInformation eventSubscriptionInfo; if (_eventsMethods.TryGetValue(methodId, out eventSubscriptionInfo) == false) { #if Matrix_Diagnostics SystemMonitor.OperationError("Failed to find corresponding method info, invocation aborted (possible dispose)."); #endif return(ProxyTypeManager.GetTypeDefaultValue(returnType)); } SuperPoolSubscription owner = _owner; if (owner == null) { #if Matrix_Diagnostics SystemMonitor.OperationError("Owner not assign, invocation aborted (possible dispose)."); #endif return(ProxyTypeManager.GetTypeDefaultValue(returnType)); } return(owner.ProcessEventRaised(this, eventSubscriptionInfo, returnType, parameters)); }
/// <summary> /// Basic asynchronous call operation. /// </summary> /// <param name="receiverId">The value of the receiver, null means call all.</param> internal bool Call <InterfaceType>(SuperPoolClient sender, IEnumerable <ComponentId> receiversIds, out InterfaceType result, out SuperPoolProxyCall call) where InterfaceType : class { call = null; result = null; // SLOW. //if (_messageBus.ContainsClient(sender.Id) == false) //{ // SystemMonitor.OperationError("Client not a member of message bus (and super pool)."); // return false; //} if (typeof(InterfaceType).IsInterface == false) { throw new Exception("Type provided not an interface."); } // Very slow !! //object[] attributes = typeof(InterfaceType).GetCustomAttributes(typeof(SuperPoolInterfaceAttribute), false); //if (attributes == null || attributes.Length == 0) //{ // SystemMonitor.Throw("Interface type [" + typeof(InterfaceType).Name + "] not marked as super pool interface."); // return false; //} ProxyTypeManager typeManager = _proxyTypeManager; if (typeManager == null) { return(false); } if (_pendingThreadsCalls.TryGetValue(Thread.CurrentThread.ManagedThreadId, out call) == false) {// We are safe from danger of someone else already adding the value with this id, // since we are the only thread with this id. call = new SuperPoolProxyCall(); // This is slow, but very rarely executed, since thread ids are reused. _pendingThreadsCalls.Add(Thread.CurrentThread.ManagedThreadId, call); } else { // Since we reuse the call, clean it up before usage. call.Clear(); } call.Processed = false; if (receiversIds != null) {// Extract the Indeces from the Ids. List <ClientId> receiversIndeces = new List <ClientId>(); foreach (ComponentId id in receiversIds) { receiversIndeces.Add((ClientId)id); } call.ReceiversIds = receiversIndeces; } else { call.ReceiversIds = null; } call.Sender = sender; result = (InterfaceType)typeManager.ObtainInterfaceProxy(typeof(InterfaceType)); return(true); }
/// <summary> /// A call has been made from us trough the proxy object. /// </summary> internal object ProcessCall(SuperPoolProxyCall proxyCall) { SuperPoolInvocation superPool = _superPool; if (superPool == null) { #if Matrix_Diagnostics SystemMonitor.OperationError("Failed to find super pool (possible dispose)."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } IMessageBus messageBus = superPool.MessageBus; if (messageBus == null) { #if Matrix_Diagnostics SystemMonitor.OperationError("Failed to find message bus (possible dispose)."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } if (proxyCall.Processed) { #if Matrix_Diagnostics SystemMonitor.OperationError("Proxy call already processed."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.DirectCall) { MessageBusClient clientInstance = messageBus.GetLocalClientInstance(proxyCall.ReceiversIds[0]); if (clientInstance == null || clientInstance is SuperPoolClient == false) { #if Matrix_Diagnostics SystemMonitor.OperationError("Direct call failed, due to client not found or corresponding."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } else {// Perform the direct call. // This is still fast, since caching is used. FastInvokeHelper.FastInvokeHandlerDelegate delegateInstance = FastInvokeHelper.GetMethodInvoker(proxyCall.MethodInfo.ProxyMethodInfo, true, true); return(delegateInstance.Invoke(((SuperPoolClient)clientInstance).Source, proxyCall.Parameters)); } } else if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.CallFirst) { ClientId firstId = this.Resolve(proxyCall.MethodInfo.ProxyMethodInfo.DeclaringType); if (firstId == null) { #if Matrix_Diagnostics SystemMonitor.OperationError("Call first failed, no client found for [" + proxyCall.MethodInfo.ProxyMethodInfo.DeclaringType.Name + "] interface."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } proxyCall.ReceiversIds = new List <ClientId>() { firstId }; } SuperPoolCall call = new SuperPoolCall(superPool.GetUniqueCallId()); call.Parameters = proxyCall.Parameters; call.MethodInfoLocal = proxyCall.MethodInfo.ProxyMethodInfo; call.State = SuperPoolCall.StateEnum.Requesting; //SuperPoolProxyCall.ModeEnum.Default ? SuperPoolCall.StateEnum.Requesting : SuperPoolCall.StateEnum.RequestingDirectCall; call.RequestResponse = proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting; proxyCall.Processed = true; foreach (ParameterInfo info in call.MethodInfoLocal.GetParameters()) {// Filter out ref, out and optional parameters. if (/*info.IsOptional ||*/ info.IsOut || info.IsRetval || info.IsOut || info.ParameterType.IsByRef) { throw new NotImplementedException("Super pool calls do not support optional, out and ref parameters"); } } // Prepare the synchronous structure (also handles waiting for the async results). SyncCallInfo syncCall = null; if (proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting) { syncCall = new SyncCallInfo(call.Id) { AsyncResultState = proxyCall.AsyncResultState, AsyncResultDelegate = proxyCall.AsyncResultDelegate, AsyncResultTimeout = proxyCall.AsyncResultTimeout, }; lock (_syncCalls) { _syncCalls[call.Id] = syncCall; } } List <ClientId> receiversIndeces = null; if (proxyCall.ReceiversIds == null) {// No receiver indicates send to all, so that is what we do. if (proxyCall.MethodInfo == null || proxyCall.MethodInfo.ProxyOwnerType == null) { #if Matrix_Diagnostics SystemMonitor.Error("Failed to establish the required proxy call parameters."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } Type interfaceType = proxyCall.MethodInfo.GetBaseInterfaceType(); if (interfaceType == null) { #if Matrix_Diagnostics SystemMonitor.Error("Failed to establish the base interface type."); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } receiversIndeces = new List <ClientId>(); foreach (ComponentId receiverId in superPool.GetInterfaceImplementors(interfaceType)) { if (receiverId != proxyCall.Sender.Id) { receiversIndeces.Add((ClientId)receiverId); } if (proxyCall.IsSynchronous && receiversIndeces.Count > 0) {// Synchronous inadressed calls only execute agains a max of one provider. break; } } } else { receiversIndeces = proxyCall.ReceiversIds; } if (receiversIndeces.Count > 0) { if (syncCall != null && proxyCall.IsSynchronous) {// Prepare the event. syncCall.Event = new ManualResetEvent(false); } Outcomes sendResult = messageBus.Send(this.Id, receiversIndeces, new Envelope(call) { DuplicationMode = EnvelopeDuplicationMode }, proxyCall.RequestConfirmTimeout, false); if (proxyCall.Outcome != null) { proxyCall.Outcome.Result = sendResult; } if (sendResult != Outcomes.Success) { #if Matrix_Diagnostics SystemMonitor.OperationError(string.Format("Failed to send proxy call [{0}].", proxyCall.ToString())); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } if (syncCall != null && proxyCall.IsSynchronous) { // Wait for response. if (syncCall.Event.WaitOne(proxyCall.Timeout.Value) == false) { // Time out. #if Matrix_Diagnostics SystemMonitor.OperationWarning(string.Format("Proxy call timed out [{0}].", proxyCall.ToString())); #endif return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } else {// Waited and awaken. return(syncCall.Response); } } } else { #if Matrix_Diagnostics SystemMonitor.OperationWarning(string.Format("Failed to find invocation recipients for call [{0}].", proxyCall.ToString())); #endif } return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); }
internal object ProcessCall(SuperPoolProxyCall proxyCall) { SuperPoolInvocation superPoolInvocation = (SuperPoolInvocation)this._superPool; if (superPoolInvocation == null) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } IMessageBus messageBus = superPoolInvocation.MessageBus; if (messageBus == null || proxyCall.Processed) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.DirectCall) { MessageBusClient localClientInstance = messageBus.GetLocalClientInstance(proxyCall.ReceiversIds[0]); if (localClientInstance == null || !(localClientInstance is SuperPoolClient)) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } else { return(FastInvokeHelper.GetMethodInvoker(proxyCall.MethodInfo.ProxyMethodInfo, true, true)(((ActiveInvocatorClient)localClientInstance).Source, proxyCall.Parameters)); } } else { if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.CallFirst) { ClientId clientId = this.Resolve(proxyCall.MethodInfo.ProxyMethodInfo.DeclaringType); if ((ComponentId)clientId == (ComponentId)null) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } proxyCall.ReceiversIds = new List <ClientId>() { clientId }; } SuperPoolCall superPoolCall = new SuperPoolCall(superPoolInvocation.GetUniqueCallId()); superPoolCall.Parameters = proxyCall.Parameters; superPoolCall.MethodInfoLocal = proxyCall.MethodInfo.ProxyMethodInfo; superPoolCall.State = SuperPoolCall.StateEnum.Requesting; superPoolCall.RequestResponse = proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting; proxyCall.Processed = true; foreach (ParameterInfo parameterInfo in superPoolCall.MethodInfoLocal.GetParameters()) { if (parameterInfo.IsOut || parameterInfo.IsRetval || parameterInfo.IsOut || parameterInfo.ParameterType.IsByRef) { throw new NotImplementedException("Super pool calls do not support optional, out and ref parameters"); } } SyncCallInfo syncCallInfo = (SyncCallInfo)null; if (proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting) { syncCallInfo = new SyncCallInfo(superPoolCall.Id) { AsyncResultState = proxyCall.AsyncResultState, AsyncResultDelegate = proxyCall.AsyncResultDelegate, AsyncResultTimeout = proxyCall.AsyncResultTimeout }; lock (this._syncCalls) this._syncCalls[superPoolCall.Id] = syncCallInfo; } List <ClientId> list; if (proxyCall.ReceiversIds == null) { if (proxyCall.MethodInfo == null || proxyCall.MethodInfo.ProxyOwnerType == null) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } Type baseInterfaceType = proxyCall.MethodInfo.GetBaseInterfaceType(); if (baseInterfaceType == null) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } list = new List <ClientId>(); foreach (ComponentId componentId in superPoolInvocation.GetInterfaceImplementors(baseInterfaceType)) { if (componentId != (ComponentId)proxyCall.Sender.Id) { list.Add((ClientId)componentId); } if (proxyCall.IsSynchronous && list.Count > 0) { break; } } } else { list = proxyCall.ReceiversIds; } if (list.Count <= 0) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } if (syncCallInfo != null && proxyCall.IsSynchronous) { syncCallInfo.Event = new ManualResetEvent(false); } Outcomes outcomes = messageBus.Send(this.Id, (IEnumerable <ClientId>)list, new Envelope((object)superPoolCall) { DuplicationMode = this.EnvelopeDuplicationMode }, proxyCall.RequestConfirmTimeout, 0 != 0); if (proxyCall.Outcome != null) { proxyCall.Outcome.Result = outcomes; } if (outcomes != Outcomes.Success || (syncCallInfo == null || !proxyCall.IsSynchronous || !syncCallInfo.Event.WaitOne(proxyCall.Timeout.Value))) { return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType)); } else { return(syncCallInfo.Response); } } }