/// <summary> /// Constructor. /// </summary> public ThreadPoolFastExecutionStrategy(bool useCommonMessageBusPool) { _useCommonMessageBusPool = useCommonMessageBusPool; GeneralHelper.GenericDelegate <Envelope> delegateInstance = new GeneralHelper.GenericDelegate <Envelope>(PerformExecution); _performExecutionDelegate = FastInvokeHelper.GetMethodInvoker(delegateInstance.Method, true, false); }
/// <summary> /// Constructor. /// </summary> public ThreadPoolFastExecutionStrategy(ArbiterSlimActiveClientStub client, bool useCommonArbiterPool) : base(client) { _useCommonArbiterPool = useCommonArbiterPool; GeneralHelper.GenericDelegate <ThreadPoolFast, Envelope> delegateInstance = new GeneralHelper.GenericDelegate <ThreadPoolFast, Envelope>(PerformExecution); _singleFastInvokeDelegate = FastInvokeHelper.GetMethodInvoker(delegateInstance.Method, false); }
/// <summary> /// Helper, obtain the correspoding fast delegate of a method info. /// </summary> public FastInvokeHelper.FastInvokeHandlerDelegate GetMessageHandler(MethodInfo methodInfo) { return(FastInvokeHelper.GetMethodInvoker(methodInfo, true, true)); //lock (_methodDelegates) //{ // if (_methodDelegates.ContainsKey(methodInfo)) // { // return _methodDelegates[methodInfo]; // } // FastInvokeHelper.FastInvokeHandlerDelegate resultHandler = FastInvokeHelper.GetMethodInvoker(methodInfo, true, true); // _methodDelegates[methodInfo] = resultHandler; // return resultHandler; //} }
/// <summary> /// /// </summary> void Initialize() { if (_messageFilter == null || _messageFilter is TransportMessageFilter == false) { _messageFilter = new TransportMessageFilter(this.SubscriptionClientID); } Type type = this.GetType(); while (type != typeof(TransportClient)) {// Gather current type members, but also gather parents private types, since those will not be available to the child class and will be missed. // Also not that the dictionary key mechanism throws if same baseMethod is entered twise - so it is a added safety feature. MethodInfo[] infos = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (MethodInfo methodInfo in infos) { object[] customAttributes = methodInfo.GetCustomAttributes(false); if (type != this.GetType() && methodInfo.IsPrivate == false) {// Since this is one of the members of the parent classes, make sure to just gather privates. // because all of the parent's protected and public methods are available from the child class. continue; } if (customAttributes.Length == 0 || customAttributes[0] is MessageReceiverAttribute == false) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType.IsSubclassOf(typeof(Message)) && (methodInfo.ReturnType == typeof(void) || methodInfo.ReturnType.IsSubclassOf(typeof(Message)) == true)) { _methodsAndMessageTypes.Add(parameters[0].ParameterType, FastInvokeHelper.GetMethodInvoker(methodInfo, true)); } else {// Warn that a baseMethod marked with the Attribute was found but will not be assigned. SystemMonitor.Error("A method [" + methodInfo.DeclaringType + "::" + methodInfo.Name + "] marked with MessageReceiverAttribute does not match parameter and return type criteria."); } } type = type.BaseType; } }
/// <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); } } }