diff --git a/Esiur/Core/AsyncReply.cs b/Esiur/Core/AsyncReply.cs index e5d99cf..1859a50 100644 --- a/Esiur/Core/AsyncReply.cs +++ b/Esiur/Core/AsyncReply.cs @@ -35,301 +35,9 @@ using System.Diagnostics; namespace Esiur.Core { - [AsyncMethodBuilder(typeof(AsyncReply<>))] - public class AsyncReply : IAsyncReply + [AsyncMethodBuilder(typeof(AsyncReplyBuilder))] + public class AsyncReply : AsyncReply { - public bool Debug = false; - - protected List> callbacks = new List>(); - protected T result; - - protected List> errorCallbacks = new List>(); - - protected List> progressCallbacks = new List>(); - - protected List> chunkCallbacks = new List>(); - - //List awaiters = new List(); - - object asyncLock = new object(); - - //public Timer timeout;// = new Timer() - protected bool resultReady = false; - AsyncException exception; - StackTrace trace; - AutoResetEvent mutex = new AutoResetEvent(false); - - public static int MaxId; - - public int Id; - - public bool Ready - { - get { return resultReady; } - - } - - - public T Wait() - { - - if (resultReady) - return result; - - if (Debug) - Console.WriteLine($"AsyncReply: {Id} Wait"); - - //mutex = new AutoResetEvent(false); - mutex.WaitOne(); - - if (Debug) - Console.WriteLine($"AsyncReply: {Id} Wait ended"); - - - return result; - } - - - public object Result - { - get { return result; } - } - - - public IAsyncReply Then(Action callback) - { - //lock (callbacksLock) - //{ - lock (asyncLock) - { - trace = new StackTrace(); - - if (resultReady) - { - if (Debug) - Console.WriteLine($"AsyncReply: {Id} Then ready"); - - callback(result); - return this; - } - - - //timeout = new Timer(x => - //{ - // // Get calling method name - // Console.WriteLine(trace.GetFrame(1).GetMethod().Name); - - // var tr = String.Join("\r\n", trace.GetFrames().Select(f => f.GetMethod().Name)); - // timeout.Dispose(); - - // tr = trace.ToString(); - // throw new Exception("Request timeout " + Id); - //}, null, 15000, 0); - - - if (Debug) - Console.WriteLine($"AsyncReply: {Id} Then pending"); - - - - callbacks.Add(callback); - - return this; - } - } - - - - public IAsyncReply Error(Action callback) - { - // lock (callbacksLock) - // { - errorCallbacks.Add(callback); - - if (exception != null) - callback(exception); - - return this; - //} - } - - public IAsyncReply Progress(Action callback) - { - //lock (callbacksLock) - //{ - progressCallbacks.Add(callback); - return this; - //} - } - - - public IAsyncReply Chunk(Action callback) - { - // lock (callbacksLock) - // { - chunkCallbacks.Add(callback); - return this; - // } - } - - public void Trigger(object result) - { - lock (asyncLock) - { - //timeout?.Dispose(); - - if (Debug) - Console.WriteLine($"AsyncReply: {Id} Trigger"); - - if (resultReady) - return; - - this.result = (T)result; - - resultReady = true; - - //if (mutex != null) - mutex.Set(); - - foreach (var cb in callbacks) - cb((T)result); - - - if (Debug) - Console.WriteLine($"AsyncReply: {Id} Trigger ended"); - - } - } - - public void TriggerError(Exception exception) - { - //timeout?.Dispose(); - - if (resultReady) - return; - - if (exception is AsyncException) - this.exception = exception as AsyncException; - else - this.exception = new AsyncException(ErrorType.Management, 0, exception.Message); - - - // lock (callbacksLock) - // { - foreach (var cb in errorCallbacks) - cb(this.exception); - // } - - mutex?.Set(); - - } - - public void TriggerProgress(ProgressType type, int value, int max) - { - //timeout?.Dispose(); - - if (resultReady) - return; - - //lock (callbacksLock) - //{ - foreach (var cb in progressCallbacks) - cb(type, value, max); - - //} - } - - - public void TriggerChunk(object value) - { - - //timeout?.Dispose(); - - if (resultReady) - return; - - //lock (callbacksLock) - //{ - foreach (var cb in chunkCallbacks) - cb((T)value); - - //} - } - - public AsyncAwaiter GetAwaiter() - { - return new AsyncAwaiter(this); - } - - - - public AsyncReply() - { - // this.Debug = true; - Id = MaxId++; - } - - public AsyncReply(T result) - { - // this.Debug = true; - resultReady = true; - this.result = result; - - Id = MaxId++; - } - - /* - public AsyncReply Then(Action callback) - { - base.Then(new Action(o => callback((T)o))); - return this; - } - - public void Trigger(T result) - { - Trigger((object)result); - } - - public Task MoveNext(CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public void Dispose() - { - } - - public AsyncReply() - { - - } - - public new Task Task - { - get - { - return base.Task.ContinueWith((t) => - { - -#if NETSTANDARD - return (T)t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t); -#else - return (T)t.GetType().GetProperty("Result").GetValue(t); -#endif - }); - } - } - - public T Current => throw new NotImplementedException(); - - public AsyncReply(T result) - : base(result) - { - - } - - */ - } } diff --git a/Esiur/Core/AsyncReplyBuilder.cs b/Esiur/Core/AsyncReplyBuilder.cs new file mode 100644 index 0000000..55afc6b --- /dev/null +++ b/Esiur/Core/AsyncReplyBuilder.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Esiur.Core +{ + public class AsyncReplyBuilder + { + AsyncReply reply; + + AsyncReplyBuilder(AsyncReply reply) + { + this.reply = reply; + } + + public static AsyncReplyBuilder Create() + { + return new AsyncReplyBuilder(new AsyncReply()); + } + + public void Start(ref TStateMachine stateMachine) + where TStateMachine : IAsyncStateMachine + { + stateMachine.MoveNext(); + } + + public void SetStateMachine(IAsyncStateMachine stateMachine) + { + Console.WriteLine("SetStateMachine"); + } + + public void SetException(Exception exception) + { + reply.TriggerError(exception); + } + + public void SetResult() + { + reply.Trigger(null); + } + + public void AwaitOnCompleted( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : INotifyCompletion + where TStateMachine : IAsyncStateMachine + { + Console.WriteLine("AwaitOnCompleted"); + + } + + public void AwaitUnsafeOnCompleted( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : ICriticalNotifyCompletion + where TStateMachine : IAsyncStateMachine + { + Console.WriteLine("AwaitUnsafeOnCompleted"); + + } + + public AsyncReply Task + { + get + { + return reply; + } + } + + } +} diff --git a/Esiur/Core/AsyncReplyBuilderGeneric.cs b/Esiur/Core/AsyncReplyBuilderGeneric.cs new file mode 100644 index 0000000..0305368 --- /dev/null +++ b/Esiur/Core/AsyncReplyBuilderGeneric.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Esiur.Core +{ + public class AsyncReplyBuilder + { + AsyncReply reply; + + AsyncReplyBuilder(AsyncReply reply) + { + this.reply = reply; + } + + public static AsyncReplyBuilder Create() + { + return new AsyncReplyBuilder(new AsyncReply()); + } + + public void Start(ref TStateMachine stateMachine) + where TStateMachine : IAsyncStateMachine + { + stateMachine.MoveNext(); + } + + public void SetStateMachine(IAsyncStateMachine stateMachine) + { + Console.WriteLine("SetStateMachine"); + } + + public void SetException(Exception exception) + { + reply.TriggerError(exception); + } + + public void SetResult(T result) + { + reply.Trigger(result); + } + + public void AwaitOnCompleted( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : INotifyCompletion + where TStateMachine : IAsyncStateMachine + { + Console.WriteLine("AwaitOnCompleted"); + + } + + public void AwaitUnsafeOnCompleted( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : ICriticalNotifyCompletion + where TStateMachine : IAsyncStateMachine + { + Console.WriteLine("AwaitUnsafeOnCompleted"); + + } + + public AsyncReply Task + { + get { + return reply; + } + } + + } +} diff --git a/Esiur/Core/AsyncReplyGeneric.cs b/Esiur/Core/AsyncReplyGeneric.cs new file mode 100644 index 0000000..7bd9070 --- /dev/null +++ b/Esiur/Core/AsyncReplyGeneric.cs @@ -0,0 +1,337 @@ +/* + +Copyright (c) 2017 Ahmed Kh. Zamil + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Esiur.Resource; +using System.Reflection; +using System.Threading; +using System.Runtime.CompilerServices; +using System.Diagnostics; + +namespace Esiur.Core +{ + [AsyncMethodBuilder(typeof(AsyncReplyBuilder<>))] + public class AsyncReply : IAsyncReply + { + + public bool Debug = false; + + protected List> callbacks = new List>(); + protected T result; + + protected List> errorCallbacks = new List>(); + + protected List> progressCallbacks = new List>(); + + protected List> chunkCallbacks = new List>(); + + //List awaiters = new List(); + + object asyncLock = new object(); + + //public Timer timeout;// = new Timer() + protected bool resultReady = false; + AsyncException exception; + StackTrace trace; + AutoResetEvent mutex = new AutoResetEvent(false); + + public static int MaxId; + + public int Id; + + public bool Ready + { + get { return resultReady; } + + } + + + public T Wait() + { + + if (resultReady) + return result; + + if (Debug) + Console.WriteLine($"AsyncReply: {Id} Wait"); + + //mutex = new AutoResetEvent(false); + mutex.WaitOne(); + + if (Debug) + Console.WriteLine($"AsyncReply: {Id} Wait ended"); + + + return result; + } + + + public object Result + { + get { return result; } + } + + + public IAsyncReply Then(Action callback) + { + //lock (callbacksLock) + //{ + lock (asyncLock) + { + trace = new StackTrace(); + + if (resultReady) + { + if (Debug) + Console.WriteLine($"AsyncReply: {Id} Then ready"); + + callback(result); + return this; + } + + + //timeout = new Timer(x => + //{ + // // Get calling method name + // Console.WriteLine(trace.GetFrame(1).GetMethod().Name); + + // var tr = String.Join("\r\n", trace.GetFrames().Select(f => f.GetMethod().Name)); + // timeout.Dispose(); + + // tr = trace.ToString(); + // throw new Exception("Request timeout " + Id); + //}, null, 15000, 0); + + + if (Debug) + Console.WriteLine($"AsyncReply: {Id} Then pending"); + + + + callbacks.Add(callback); + + return this; + } + } + + + + public IAsyncReply Error(Action callback) + { + // lock (callbacksLock) + // { + errorCallbacks.Add(callback); + + if (exception != null) + callback(exception); + + return this; + //} + } + + public IAsyncReply Progress(Action callback) + { + //lock (callbacksLock) + //{ + progressCallbacks.Add(callback); + return this; + //} + } + + + public IAsyncReply Chunk(Action callback) + { + // lock (callbacksLock) + // { + chunkCallbacks.Add(callback); + return this; + // } + } + + public void Trigger(object result) + { + lock (asyncLock) + { + //timeout?.Dispose(); + + if (Debug) + Console.WriteLine($"AsyncReply: {Id} Trigger"); + + if (resultReady) + return; + + this.result = (T)result; + + resultReady = true; + + //if (mutex != null) + mutex.Set(); + + foreach (var cb in callbacks) + cb((T)result); + + + if (Debug) + Console.WriteLine($"AsyncReply: {Id} Trigger ended"); + + } + } + + public void TriggerError(Exception exception) + { + //timeout?.Dispose(); + + if (resultReady) + return; + + if (exception is AsyncException) + this.exception = exception as AsyncException; + else + this.exception = new AsyncException(ErrorType.Management, 0, exception.Message); + + + // lock (callbacksLock) + // { + foreach (var cb in errorCallbacks) + cb(this.exception); + // } + + mutex?.Set(); + + } + + public void TriggerProgress(ProgressType type, int value, int max) + { + //timeout?.Dispose(); + + if (resultReady) + return; + + //lock (callbacksLock) + //{ + foreach (var cb in progressCallbacks) + cb(type, value, max); + + //} + } + + + public void TriggerChunk(object value) + { + + //timeout?.Dispose(); + + if (resultReady) + return; + + //lock (callbacksLock) + //{ + foreach (var cb in chunkCallbacks) + cb((T)value); + + //} + } + + public AsyncAwaiter GetAwaiter() + { + return new AsyncAwaiter(this); + } + + + + public AsyncReply() + { + // this.Debug = true; + Id = MaxId++; + } + + public AsyncReply(T result) + { + // this.Debug = true; + resultReady = true; + this.result = result; + + Id = MaxId++; + } + + /* + public AsyncReply Then(Action callback) + { + base.Then(new Action(o => callback((T)o))); + return this; + } + + public void Trigger(T result) + { + Trigger((object)result); + } + + public Task MoveNext(CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + } + + public AsyncReply() + { + + } + + public new Task Task + { + get + { + return base.Task.ContinueWith((t) => + { + +#if NETSTANDARD + return (T)t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t); +#else + return (T)t.GetType().GetProperty("Result").GetValue(t); +#endif + }); + } + } + + public T Current => throw new NotImplementedException(); + + public AsyncReply(T result) + : base(result) + { + + } + + */ + + + + } +} diff --git a/Esiur/Net/NetworkServer.cs b/Esiur/Net/NetworkServer.cs index d03a2d4..e3596ce 100644 --- a/Esiur/Net/NetworkServer.cs +++ b/Esiur/Net/NetworkServer.cs @@ -306,9 +306,7 @@ namespace Esiur.Net } // Accept more - var l = listener.Accept(); - - l.Then(NewConnection); + listener.Accept().Then(NewConnection); //l.timeout?.Dispose(); sock.Begin();