/// <summary> /// Checks all Methods that returns Task or Task`1 if their naming is according to the convention. /// </summary> /// <param name="builder"></param> public void CheckAsyncMethodsNomenclature(Builder builder) { var task = new __Task(); var taskGeneric = new __Task_1(); var methods = builder .GetTypes(SearchContext.Module) .SelectMany(x => x.Methods) .Where(x => { if (x.IsGenerated) { return(false); } if (x.Name.EndsWith("Action")) { return(false); } if (x.Name.EndsWith("Async")) { return(false); } if (x.ReturnType == __Task.Type || x.ReturnType == __Task_1.Type) { return(true); } return(false); }); foreach (var item in methods) { this.Log(LogTypes.Warning, item, $"The method '{item.Name}' in '{item.OriginType.Fullname}' is async, but does not have an 'Async' suffix."); } }
private void InterceptMethods(Builder builder, IEnumerable <BuilderType> attributes) { if (!attributes.Any()) { return; } var stopwatch = Stopwatch.StartNew(); var iMethodInterceptor = new __IMethodInterceptor(builder); var asyncTaskMethodBuilder = new __AsyncTaskMethodBuilder(builder); var asyncTaskMethodBuilderGeneric = new __AsyncTaskMethodBuilder_1(builder); var syncRoot = new __ISyncRoot(builder); var task = new __Task(builder); var exception = new __Exception(builder); var methods = builder .FindMethodsByAttributes(attributes) .GroupBy(x => new MethodKey(x.Method, x.AsyncMethod)) .Select(x => new MethodBuilderInfo(x.Key, x.Select(y => new MethodBuilderInfoItem(y, iMethodInterceptor)))) .ToArray(); foreach (var method in methods) { this.LogInfo($"Implementing interceptors in method {method.Key.Method}"); var targetedMethod = method.Key.AsyncMethod == null ? method.Key.Method : method.Key.AsyncMethod; var attributedMethod = method.Key.Method; method.AddThisReferenceToAsyncMethod(); var typeInstance = method.GetAsyncMethodTypeInstace(); var interceptorField = new Field[method.Item.Length]; if (method.RequiresSyncRootField) { foreach (var ctors in targetedMethod.DeclaringType.GetRelevantConstructors()) { ctors.NewCode().Assign(method.SyncRoot).NewObj(builder.GetType(typeof(object)).Import().ParameterlessContructor).Insert(InsertionPosition.Beginning); } } targetedMethod .NewCode() .Context(x => { for (int i = 0; i < method.Item.Length; i++) { var item = method.Item[i]; var name = $"<{targetedMethod.Name}>_attrib{i}_{item.Attribute.Identification}"; interceptorField[i] = targetedMethod.DeclaringType.CreateField(targetedMethod.Modifiers.GetPrivate(), item.Interface.Type, name); x.Load(interceptorField[i]).IsNull().Then(y => { y.Assign(interceptorField[i]).NewObj(item.Attribute); if (item.HasSyncRootInterface) { y.Load(interceptorField[i]).As(syncRoot.Type).Call(syncRoot.SyncRoot, method.SyncRoot); } }); item.Attribute.Remove(); } }) .Try(x => { for (int i = 0; i < method.Item.Length; i++) { var item = method.Item[i]; x.Load(interceptorField[i]).As(item.Interface.Type).Call(item.Interface.OnEnter, attributedMethod.DeclaringType, typeInstance, attributedMethod, x.GetParametersArray()); } x.OriginalBody(); // Special case for async methods if (method.Key.AsyncMethod != null && method.Key.Method.ReturnType.Fullname == task.Type.Fullname) // Task return { var exceptionVar = x.CreateVariable(exception.Type); x.Assign(exceptionVar).Set( x.NewCode().Call(method.Key.AsyncMethod.DeclaringType.GetField("<>t__builder"), asyncTaskMethodBuilder.GetTask) .Call(task.GetException)); x.Load(exceptionVar).IsNotNull().Then(y => { for (int i = 0; i < method.Item.Length; i++) { y.Load(interceptorField[i]).Callvirt(method.Item[i].Interface.OnException, exceptionVar); } }); } else if (method.Key.AsyncMethod != null) // Task<> return { var exceptionVar = x.CreateVariable(exception.Type); var taskArgument = method.Key.Method.ReturnType.GetGenericArgument(0); x.Assign(exceptionVar).Set( x.NewCode().Call(method.Key.AsyncMethod.DeclaringType.GetField("<>t__builder"), asyncTaskMethodBuilderGeneric.GetTask.MakeGeneric(taskArgument)) .Call(task.GetException)); x.Load(exceptionVar).IsNotNull().Then(y => { for (int i = 0; i < method.Item.Length; i++) { y.Load(interceptorField[i]).Callvirt(method.Item[i].Interface.OnException, exceptionVar); } }); } }) .Catch(exception.Type, x => { if (method.Key.AsyncMethod == null) { for (int i = 0; i < method.Item.Length; i++) { x.Load(interceptorField[i]).As(method.Item[i].Interface.Type).Call(method.Item[i].Interface.OnException, x.Exception); } } x.Rethrow(); }) .Finally(x => { for (int i = 0; i < method.Item.Length; i++) { x.Load(interceptorField[i]).As(method.Item[i].Interface.Type).Call(method.Item[i].Interface.OnExit); } }) .EndTry() .Return() .Replace(); } ; stopwatch.Stop(); this.LogInfo($"Implementing method interceptors took {stopwatch.Elapsed.TotalMilliseconds}ms"); }
public Task <UdpReceiveResult> ReceiveAsync() { // workaround... int malloc_bytearray_paddingleft = 4; ConsoleExtensions.trace("enter UdpClient ReceiveAsync"); var buff = stackalloc byte[0xfff]; socket_h.sockaddr_in sender; var sizeof_sender = sizeof(socket_h.sockaddr_in); //ConsoleExtensions.trace("before recvfrom"); // http://pubs.opengroup.org/onlinepubs/009695399/functions/recvfrom.html // Upon successful completion, recvfrom() shall return the length of the message in bytes. var recvfromret = s.recvfrom(buff, 0xfff, 0, (socket_h.sockaddr *) & sender, &sizeof_sender); // sent by? //I/xNativeActivity(24024): X:\jsc.svn\examples\c\android\Test\NDKUdpClient\NDKUdpClient\xNativeActivity.cs:167 recvfrom: 116 errno: 22 Invalid argument //I/xNativeActivity(24024): X:\jsc.svn\examples\c\android\Test\NDKUdpClient\NDKUdpClient\xNativeActivity.cs:168 SenderAddrSize: 16 errno: 22 Invalid argument ConsoleExtensions.tracei("recvfrom: ", recvfromret); //tracei("sockaddr_in: ", sizeof_sender); buff[recvfromret] = 0; //Task<UdpReceiveResult> // lets fill up GC. collect when thread shuts down? //var Buffer = new byte[recvfromret]; // what about digitally signing the buffer? //var le_bytes = (byte*)stdlib_h.malloc(stdlib_h.malloc_bytearray_paddingleft + recvfromret); var le_bytes = (byte *)stdlib_h.malloc(malloc_bytearray_paddingleft + recvfromret); // I/xNativeActivity(12673): [2781936] \UdpClient.cs:110 recvfrom: 3 //I/xNativeActivity(12673): [2781936] \UdpClient.cs:138 bytesLength: 50331648 ConsoleExtensions.trace("set le_ipointer"); var le_ipointer = (int *)le_bytes; *le_ipointer = recvfromret; //int32_5 = ((int*)byte_4); //*int32_5 = num3; { ConsoleExtensions.trace("get le_ipointer"); var lei = *le_ipointer; ConsoleExtensions.tracei("lei: ", lei); } // Z:\jsc.svn\examples\c\Test\TestPointerOffset\Class1.cs #region ___bytes // byte_7 = ((unsigned char*)(&(byte_4[1]))); var ___bytes = le_bytes + malloc_bytearray_paddingleft; for (int i = 0; i < recvfromret; i++) { var byte0 = buff[i]; ConsoleExtensions.tracei("set byte0: ", byte0); //Buffer[i] = buff[i]; ___bytes[i] = byte0; } #endregion { ConsoleExtensions.trace("get le_ipointer"); var lei = *le_ipointer; ConsoleExtensions.tracei("lei: ", lei); } var bytes = __cast(___bytes); { ConsoleExtensions.trace("---"); var byte0 = bytes[0]; ConsoleExtensions.tracei("byte0: ", byte0); var bytesLength = bytes.Length; ConsoleExtensions.tracei("bytesLength: ", bytesLength); } // ptr? //{ // var xbytes = __cast(bytes); // var xlebytes = xbytes - 4; // var ile = (int*)xlebytes; // ConsoleExtensions.tracei("ile: ", *ile); //} //I/xNativeActivity( 2541): [2777960] \UdpClient.cs:199 set task_Result_Buffer: -192277436 //I/xNativeActivity( 2541): [2777960] \UdpClient.cs:202 Result.Buffer.Length: 2 //I/xNativeActivity( 2541): [2777960] \UdpClient.cs:211 got task_Result //I/xNativeActivity( 2541): [2777960] \UdpClient.cs:229 got task_Result_Buffer: -867631102 ConsoleExtensions.tracei64("set task_Result_Buffer: ", (long)__cast(bytes)); //var Result = new UdpReceiveResult(bytes, null); var Result = new __UdpReceiveResult(bytes, null); //result13 = ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult__ctor_6000072(__new_ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult(1), byteArray11, NULL); // ScriptCoreLibAndroidNDK_Library_ConsoleExtensions_tracei64("Result: ", (long long)result13, "z:\x5c""jsc.svn\x5c""core\x5c""ScriptCoreLibAndroidNDK\x5c""ScriptCoreLibAndroidNDK\x5c""BCLImplementation\x5c""System\x5c""Net\x5c""Sockets\x5c""UdpClient.cs", 212); // \UdpClient.cs:210 Result: 0 ConsoleExtensions.tracei64("Result: ", (long)(object)Result); //typedef struct tag_ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult //{ // struct tag_ScriptCoreLibJava_BCLImplementation_System_Net___IPEndPoint* _RemoteEndPoint_k__BackingField; // unsigned char* _Buffer_k__BackingField; //} ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult, *LPScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult; //ConsoleExtensions.tracei("Result.Buffer.Length: ", Result.Buffer.Length); //var task = new __Task<UdpReceiveResult>(); var task = new __Task <__UdpReceiveResult>(); //typedef struct tag_ScriptCoreLibNative_BCLImplementation_System___Task_1 //{ // void* _Result_k__BackingField; //} ScriptCoreLibNative_BCLImplementation_System___Task_1, *LPScriptCoreLibNative_BCLImplementation_System___Task_1; task.Result = (__UdpReceiveResult)(object)Result; var task_Result = task.Result; ConsoleExtensions.trace("got task_Result, crash?"); ConsoleExtensions.tracei64("task_Result: ", (long)(object)task_Result); //Task<UdpReceiveResult> t = new __Task<UdpReceiveResult> { Result = Result }; // ScriptCoreLibAndroidNDK_Library_ConsoleExtensions_tracei("t.Result.Buffer.Length: ", (int)((signed int)(/* ldlen */ *(int*)(&(ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult_get_Buffer((ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult*)(&result18))[-4])))), "z:\x5c""jsc.svn\x5c""core\x5c""ScriptCoreLibAndroidNDK\x5c""ScriptCoreLibAndroidNDK\x5c""BCLImplementation\x5c""System\x5c""Net\x5c""Sockets\x5c""UdpClient.cs", 211); // struct?? //if (task_Result == null) //{ //} //else { // byteArray19 = ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult_get_Buffer((ScriptCoreLib_Shared_BCLImplementation_System_Net_Sockets___UdpReceiveResult*)(&result18)); var task_Result_Buffer = task_Result.Buffer; // \UdpClient.cs:226 got task_Result_Buffer: 848560130 ConsoleExtensions.tracei64("got task_Result_Buffer: ", (long)__cast(task_Result_Buffer)); ConsoleExtensions.tracei("t.Result.Buffer.Length: ", task_Result_Buffer.Length); // t.Result.Buffer.Length: 2 } return((Task <UdpReceiveResult>)(object) task); }
private void ImplementTimedCache(Builder builder) { if (!builder.TypeExists(__TimedCacheAttribute.TypeName)) { return; } var timedCacheAttribute = new __TimedCacheAttribute(builder); var methods = builder.FindMethodsByAttribute(timedCacheAttribute.Type.Fullname); if (!methods.Any()) { return; } var task = new __Task(builder); var task_1 = new __Task_1(builder); foreach (var method in methods) { this.Log($"Implementing TimedCache in method {method.Method.Name}"); if (method.Method.ReturnType.Fullname == "System.Void") { this.Log(LogTypes.Warning, method.Method, "TimedCacheAttribute does not support void return types"); continue; } var keyName = "<>timedcache_key"; var timecacheVarName = "<>timedcache"; if (method.AsyncMethod == null && method.Method.ReturnType.Inherits(task.Type.Fullname)) { this.Log(LogTypes.Error, method.Method, $"- TimedCacheAttribute for method {method.Method.Name} will not be implemented. Methods that returns 'Task' without async are not supported."); } else if (method.AsyncMethod == null) { method.Method.NewCode() .Context(x => { var timedCache = x.CreateVariable(timecacheVarName, method.Attribute.Type); var key = x.CreateVariable(keyName, timedCacheAttribute.CreateKey); var returnVariable = x.GetReturnVariable(); x.Assign(timedCache).NewObj(method); // Create a cache key x.Call(timedCacheAttribute.CreateKey, method.Method.Fullname, x.GetParametersArray()) .StoreLocal(key); // check x.Load(timedCache).Call(timedCacheAttribute.HasCache, key) .IsTrue().Then(y => { y.Load(timedCache).Call(timedCacheAttribute.GetCache, key) .As(method.Method.ReturnType) .StoreLocal(returnVariable) .Return(); }); x.OriginalBodyNewMethod().StoreLocal(returnVariable); // Set the cache x.Load(timedCache).Call(timedCacheAttribute.SetCache, key, returnVariable); x.Load(returnVariable).Return(); }) .Replace(); } else if (method.AsyncMethod != null) { method.Method.NewCode() .Context(x => { var taskReturnType = method.Method.ReturnType.GetGenericArgument(0); var timedCache = x.CreateVariable(timecacheVarName, method.Attribute.Type); var cacheKey = x.CreateVariable(typeof(string)); x.Assign(cacheKey).Set(x.NewCode().Call(timedCacheAttribute.CreateKey, method.Method.Fullname, x.GetParametersArray())); x.Assign(timedCache).NewObj(method); x.Load(timedCache).Call(timedCacheAttribute.HasCache, cacheKey) .IsTrue().Then(y => { y.Call(task_1.FromResult.MakeGeneric(taskReturnType), y.NewCode().Call(timedCache, timedCacheAttribute.GetCache, cacheKey).As(taskReturnType)) .Return(); }); }).Insert(InsertionPosition.Beginning); method.Method.NewCode() .Context(x => { var taskReturnType = method.Method.ReturnType.GetGenericArgument(0); var returnVariable = x.GetReturnVariable(); x.LoadVariable(2).Call(timedCacheAttribute.SetCache, x.NewCode().LoadVariable(3), x.NewCode().Call(returnVariable, task_1.GetResult.MakeGeneric(taskReturnType))); }).Insert(InsertionPosition.End); } method.Attribute.Remove(); } }
private void ImplementMethodCache(Builder builder) { var methods = builder.FindMethodsByAttribute("Cauldron.Interception.CacheAttribute"); if (!methods.Any()) { return; } var task = new __Task(builder); var task_1 = new __Task_1(builder); foreach (var method in methods) { this.LogInfo($"Implementing Cache for method {method.Method.Name}"); if (method.Method.ReturnType.Fullname == "System.Void") { this.LogWarning("CacheAttribute does not support void return types"); continue; } var cacheField = $"<{method.Method.Name}>m__MethodCache_{method.Identification}"; if (method.AsyncMethod == null && method.Method.ReturnType.Inherits(task.Type.Fullname)) { this.LogWarning($"- CacheAttribute for method {method.Method.Name} will not be implemented. Methods that returns 'Task' without async are not supported."); } else if (method.AsyncMethod == null) { method.Method.NewCode() .Context(x => { var cache = method.Method.DeclaringType.CreateField(method.Method.Modifiers.GetPrivate(), method.Method.ReturnType, cacheField); var returnVariable = x.GetReturnVariable(); x.Load(cache).IsNull().Then(y => { y.OriginalBody().StoreLocal(returnVariable).Return(); }) .Load(cache).Return(); }) .Replace(); } else if (method.AsyncMethod != null) { method.Method.NewCode() .Context(x => { var taskReturnType = method.Method.ReturnType.GetGenericArgument(0); var cache = method.Method.DeclaringType.CreateField(method.Method.Modifiers.GetPrivate(), taskReturnType, cacheField); x.Load(cache).IsNotNull().Then(y => { y.Call(task_1.FromResult.MakeGeneric(taskReturnType), cache).Return(); }); }).Insert(InsertionPosition.Beginning); method.Method.NewCode() .Context(x => { var taskReturnType = method.Method.ReturnType.GetGenericArgument(0); var cache = method.Method.DeclaringType.GetField(cacheField); var returnVariable = x.GetReturnVariable(); x.Assign(cache).Set(x.NewCode().Call(returnVariable, task_1.GetResult.MakeGeneric(taskReturnType))); }).Insert(InsertionPosition.End); } method.Attribute.Remove(); } }
private void InterceptSimpleMethods(Builder builder, IEnumerable <BuilderType> attributes) { if (!attributes.Any()) { return; } using (new StopwatchLog(this, "method simple")) { var asyncTaskMethodBuilder = new __AsyncTaskMethodBuilder(); var asyncTaskMethodBuilderGeneric = new __AsyncTaskMethodBuilder_1(); var syncRoot = new __ISyncRoot(); var task = new __Task(); var exception = new __Exception(); var methods = builder .FindMethodsByAttributes(attributes) .Where(x => !x.Method.IsPropertyGetterSetter) .GroupBy(x => new MethodKey(x.Method, x.AsyncMethod)) .Select(x => new MethodBuilderInfo <MethodBuilderInfoItem <__ISimpleMethodInterceptor> >(x.Key, x.Select(y => new MethodBuilderInfoItem <__ISimpleMethodInterceptor>(y, __ISimpleMethodInterceptor.Instance)))) .OrderBy(x => x.Key.Method.DeclaringType.Fullname) .ToArray(); foreach (var method in methods) { if (method.Item == null || method.Item.Length == 0) { continue; } this.Log($"Implementing method interceptors: {method.Key.Method.DeclaringType.Name.PadRight(40, ' ')} {method.Key.Method.Name}({string.Join(", ", method.Key.Method.Parameters.Select(x => x.Name))})"); var targetedMethod = method.Key.AsyncMethod ?? method.Key.Method; var attributedMethod = method.Key.Method; var typeInstance = method.Key.Method.AsyncMethodHelper.Instance; var interceptorField = new Field[method.Item.Length]; if (method.RequiresSyncRootField) { if (method.SyncRoot.IsStatic) { targetedMethod.AsyncOriginType.CreateStaticConstructor().NewCode() .Assign(method.SyncRoot).NewObj(builder.GetType(typeof(object)).Import().ParameterlessContructor) .Insert(InsertionPosition.Beginning); } else { foreach (var ctors in targetedMethod.AsyncOriginType.GetRelevantConstructors().Where(x => x.Name == ".ctor")) { ctors.NewCode().Assign(method.SyncRoot).NewObj(builder.GetType(typeof(object)).Import().ParameterlessContructor).Insert(InsertionPosition.Beginning); } } } var coder = targetedMethod .NewCode() .Context(x => { for (int i = 0; i < method.Item.Length; i++) { var item = method.Item[i]; var name = $"<{targetedMethod.Name}>_attrib{i}_{item.Attribute.Identification}"; interceptorField[i] = targetedMethod.AsyncOriginType.CreateField(targetedMethod.Modifiers.GetPrivate(), item.Interface.ToBuilderType, name); interceptorField[i].CustomAttributes.AddNonSerializedAttribute(); x.Load(interceptorField[i]).IsNull().Then(y => { y.Assign(interceptorField[i]).NewObj(item.Attribute); if (item.HasSyncRootInterface) { y.Load(interceptorField[i]).As(__ISyncRoot.Type).Call(syncRoot.SyncRoot, method.SyncRoot); } ImplementAssignMethodAttribute(builder, method.Item[i].AssignMethodAttributeInfos, interceptorField[i], item.Attribute.Attribute.Type, x); }); x.Load(interceptorField[i]).Call(item.Interface.OnEnter, attributedMethod.OriginType, typeInstance, attributedMethod, x.GetParametersArray()); item.Attribute.Remove(); } }); var position = coder.GetFirstOrDefaultPosition(x => x.OpCode == OpCodes.Stelem_Ref); if (position == null) { coder.Insert(InsertionPosition.Beginning); } else { coder.Insert(InsertionAction.After, position); } } ; } }