You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2016/06/17 15:33:43 UTC
ignite git commit: IGNITE-2877 .NET: Compile and cache delegates for
service method invocation
Repository: ignite
Updated Branches:
refs/heads/master 00a60b951 -> fbba10219
IGNITE-2877 .NET: Compile and cache delegates for service method invocation
This closes #690
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fbba1021
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fbba1021
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fbba1021
Branch: refs/heads/master
Commit: fbba10219281dbf6b3a7cf369dbc1c08640a4cba
Parents: 00a60b9
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Jun 17 18:33:32 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Jun 17 18:33:32 2016 +0300
----------------------------------------------------------------------
.../Services/ServicesTest.cs | 5 +--
.../Impl/Common/DelegateConverter.cs | 44 ++++++++++++++++++++
.../Impl/Services/ServiceProxyInvoker.cs | 14 +++----
3 files changed, 52 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/fbba1021/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
index e114f5a..2bacf50 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
@@ -321,8 +321,7 @@ namespace Apache.Ignite.Core.Tests.Services
// .. but setter does not
var ex = Assert.Throws<ServiceInvocationException>(() => { prx.TestProperty = new object(); });
- Assert.AreEqual("Object of type 'System.Object' cannot be converted to type 'System.Int32'.",
- ex.InnerException.Message);
+ Assert.AreEqual("Specified cast is not valid.", ex.InnerException.Message);
}
/// <summary>
@@ -528,7 +527,7 @@ namespace Apache.Ignite.Core.Tests.Services
// Basics
Assert.IsTrue(svc.isInitialized());
- Assert.IsTrue(svc.isExecuted());
+ Assert.IsTrue(TestUtils.WaitForCondition(() => svc.isExecuted(), 500));
Assert.IsFalse(svc.isCancelled());
// Primitives
http://git-wip-us.apache.org/repos/asf/ignite/blob/fbba1021/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
index 9a0f789..ff61e28 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
@@ -152,6 +152,50 @@ namespace Apache.Ignite.Core.Impl.Common
return Expression.Lambda<T>(callExpr, argParams).Compile();
}
+ /// <summary>
+ /// Compiles a function with a single object[] argument which maps array items to actual arguments.
+ /// </summary>
+ /// <param name="method">Method.</param>
+ /// <returns>
+ /// Compiled function that calls specified method.
+ /// </returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
+ public static Func<object, object[], object> CompileFuncFromArray(MethodInfo method)
+ {
+ Debug.Assert(method != null);
+ Debug.Assert(method.DeclaringType != null);
+
+ var targetParam = Expression.Parameter(typeof(object));
+ var targetParamConverted = Expression.Convert(targetParam, method.DeclaringType);
+
+ var arrParam = Expression.Parameter(typeof(object[]));
+
+ var methodParams = method.GetParameters();
+ var argParams = new Expression[methodParams.Length];
+
+ for (var i = 0; i < methodParams.Length; i++)
+ {
+ var arrElem = Expression.ArrayIndex(arrParam, Expression.Constant(i));
+ argParams[i] = Expression.Convert(arrElem, methodParams[i].ParameterType);
+ }
+
+ Expression callExpr = Expression.Call(targetParamConverted, method, argParams);
+
+ if (callExpr.Type == typeof(void))
+ {
+ // Convert action to function
+ var action = Expression.Lambda<Action<object, object[]>>(callExpr, targetParam, arrParam).Compile();
+ return (obj, args) =>
+ {
+ action(obj, args);
+ return null;
+ };
+ }
+
+ callExpr = Expression.Convert(callExpr, typeof(object));
+
+ return Expression.Lambda<Func<object, object[], object>>(callExpr, targetParam, arrParam).Compile();
+ }
/// <summary>
/// Compiles a generic ctor with arbitrary number of arguments.
http://git-wip-us.apache.org/repos/asf/ignite/blob/fbba1021/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxyInvoker.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxyInvoker.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxyInvoker.cs
index 3c34886..bf6cd16 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxyInvoker.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxyInvoker.cs
@@ -32,8 +32,8 @@ namespace Apache.Ignite.Core.Impl.Services
internal static class ServiceProxyInvoker
{
/** Cached method info. */
- private static readonly CopyOnWriteConcurrentDictionary<Tuple<Type, string, int>, MethodInfo> Methods =
- new CopyOnWriteConcurrentDictionary<Tuple<Type, string, int>, MethodInfo>();
+ private static readonly CopyOnWriteConcurrentDictionary<Tuple<Type, string, int>, Func<object, object[], object>> Methods =
+ new CopyOnWriteConcurrentDictionary<Tuple<Type, string, int>, Func<object, object[], object>>();
/// <summary>
/// Invokes the service method according to data from a stream,
@@ -69,14 +69,14 @@ namespace Apache.Ignite.Core.Impl.Services
/// <summary>
/// Finds suitable method in the specified type, or throws an exception.
/// </summary>
- private static MethodBase GetMethodOrThrow(Type svcType, string methodName, object[] arguments)
+ private static Func<object, object[], object> GetMethodOrThrow(Type svcType, string methodName, object[] arguments)
{
Debug.Assert(svcType != null);
Debug.Assert(!string.IsNullOrWhiteSpace(methodName));
// 0) Check cached methods
var cacheKey = Tuple.Create(svcType, methodName, arguments.Length);
- MethodInfo res;
+ Func<object, object[], object> res;
if (Methods.TryGetValue(cacheKey, out res))
return res;
@@ -89,9 +89,7 @@ namespace Apache.Ignite.Core.Impl.Services
if (methods.Length == 1)
{
// Update cache only when there is a single method with a given name and arg count.
- Methods.GetOrAdd(cacheKey, x => methods[0]);
-
- return methods[0];
+ return Methods.GetOrAdd(cacheKey, x => DelegateConverter.CompileFuncFromArray(methods[0]));
}
if (methods.Length == 0)
@@ -104,7 +102,7 @@ namespace Apache.Ignite.Core.Impl.Services
methods = methods.Where(m => AreMethodArgsCompatible(arguments, m.GetParameters())).ToArray();
if (methods.Length == 1)
- return methods[0];
+ return (obj, args) => methods[0].Invoke(obj, args);
// 3) 0 or more than 1 matching method - throw.
var argsString = arguments.Length == 0