public async Task RunAsync() { // Do warmup rounds for (var i = 0L; i < WARMUP; i++) { await m_channel.ReadAsync(); } Console.WriteLine("Warmup complete, measuring"); for (int r = 0; r < REPEATS; r++) { // Measure the run var start = DateTime.Now; for (var i = 0L; i < ROUNDS; i++) { await m_channel.ReadAsync(); } var finish = DateTime.Now; // Report Console.WriteLine("Time per iteration: {0} microseconds", ((finish - start).TotalMilliseconds * 1000) / ROUNDS); Console.WriteLine("Time per communication: {0} microseconds", ((finish - start).TotalMilliseconds * 1000) / ROUNDS / 4); } // Cleanup m_channel.Retire(); }
/// <summary> /// Runs a repeated parallel operation /// </summary> /// <returns>An awaitable task.</returns> /// <param name="source">The channel where requests are read from</param> /// <param name="handler">The method to invoke for each item</param> /// <param name="token">Token.</param> /// <param name="maxparallel">The maximum parallelism to use.</param> /// <param name="errorHandler">The error handler</param> /// <typeparam name="T">The type of data elements to handle</typeparam> public static Task RunParallelAsync <T>(IReadChannel <T> source, Func <T, Task> handler, System.Threading.CancellationToken token, int maxparallel = 10, Func <T, Exception, Task> errorHandler = null) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (maxparallel <= 0) { throw new ArgumentOutOfRangeException(nameof(maxparallel), maxparallel, "The size of the queue must be greater than zero"); } return(AutomationExtensions.RunTask( new { Requests = source }, async self => { using (var tp = new TaskPool <T>(maxparallel, errorHandler)) while (true) { if (token.IsCancellationRequested) { throw new TaskCanceledException(); } await tp.Run(await source.ReadAsync(), handler).ConfigureAwait(false); } })); }
/// <summary> /// Reads the channel in a probing and asynchronous manner /// </summary> /// <param name="self">The channel to read from</param> /// <param name="waittime">The amount of time to wait before cancelling</param> /// <typeparam name="T">The channel data type parameter.</typeparam> /// <returns>True if the read succeeded, false otherwise</returns> public static Task <KeyValuePair <bool, T> > TryReadAsync <T>(this IReadChannel <T> self, TimeSpan waittime) { return(self.ReadAsync(new TimeoutOffer(waittime)).ContinueWith(x => { if (x.IsFaulted || x.IsCanceled) { return new KeyValuePair <bool, T>(false, default(T)); } return new KeyValuePair <bool, T>(true, x.Result); })); }
/// <summary> /// Reads the channel in a probing and asynchronous manner /// </summary> /// <param name="self">The channel to read from</param> /// <typeparam name="T">The channel data type parameter.</typeparam> /// <returns>True if the read succeeded, false otherwise</returns> public static Task <KeyValuePair <bool, T> > TryReadAsync <T>(this IReadChannel <T> self) { return(self.ReadAsync(Timeout.Immediate, null).ContinueWith(x => { if (x.IsFaulted || x.IsCanceled) { return new KeyValuePair <bool, T>(false, default(T)); } return new KeyValuePair <bool, T>(true, x.Result); })); }
/// <summary> /// Read from the channel in a probing manner /// </summary> /// <param name="self">The channel to read from</param> /// <param name="result">The read result</param> /// <typeparam name="T">The channel data type parameter.</typeparam> /// <returns>True if the read succeeded, false otherwise</returns> public static bool TryRead <T>(this IReadChannel <T> self, out T result) { var res = self.ReadAsync(new TimeoutOffer(Timeout.Immediate)).WaitForTask(); if (res.IsFaulted || res.IsCanceled) { result = default(T); return(false); } else { result = res.Result; return(true); } }
/// <summary> /// Runs the identity process, which simply forwards a value. /// </summary> /// <param name="chan_read">The channel to read from</param> /// <param name="chan_write">The channel to write to</param> private static async void RunIdentity(IReadChannel <T> chan_read, IWriteChannel <T> chan_write) { try { while (true) { await chan_write.WriteAsync(await chan_read.ReadAsync()); } } catch (RetiredException) { chan_read.Retire(); chan_write.Retire(); } }
public async override Task RunAsync() { try { while (true) { await m_output.WriteAsync(await m_input.ReadAsync() + 1); } } catch (RetiredException) { m_input.Retire(); m_output.Retire(); } }
public async override Task RunAsync() { try { while(m_repeat-- > 0) await m_output.WriteAsync(m_value); while (true) await m_output.WriteAsync(await m_input.ReadAsync()); } catch (RetiredException) { m_input.Retire(); m_output.Retire(); } }
/// <summary> /// Read from the channel in a blocking manner /// </summary> /// <param name="self">The channel to read from</param> /// <param name="timeout">The maximum time to wait for a value</param> /// <returns>>The value read from the channel</returns> /// <typeparam name="T">The channel data type parameter.</typeparam> public static T Read <T>(this IReadChannel <T> self, TimeSpan timeout) { try { return(self.ReadAsync(new TimeoutOffer(timeout)).WaitForTask().Result); } catch (AggregateException aex) { if (aex.Flatten().InnerExceptions.Count == 1) { throw aex.InnerException; } throw; } }
/// <summary> /// A process that reads numbers and discards those that are /// divisible by a certain number and forwards the rest /// </summary> /// <returns>The awaitable task that represents the process</returns> /// <param name="number">The number used to test and filter divisible numbers with.</param> /// <param name="input">The channel where data is read from.</param> /// <param name="output">The channel where non-multiple values are written to.</param> private static async Task RunNoMultiplesAsync(long number, IReadChannel <long> input, IWriteChannel <long> output) { try { while (true) { var v = await input.ReadAsync(); if (v % number != 0) { await output.WriteAsync(v); } } } catch (RetiredException) { input.Retire(); output.Retire(); } }
/// <summary> /// Runs the delta process, which copies the value it reads onto two different channels /// </summary> /// <param name="chan_read">The channel to read from</param> /// <param name="chan_a">The channel to write to</param> /// <param name="chan_b">The channel to write to</param> private static async void RunDelta(IReadChannel <T> chan_read, IWriteChannel <T> chan_a, IWriteChannel <T> chan_b) { try { while (true) { var value = await chan_read.ReadAsync(); await Task.WhenAll( chan_a.WriteAsync(value), chan_b.WriteAsync(value) ); } } catch (RetiredException) { chan_read.Retire(); chan_a.Retire(); chan_b.Retire(); } }
/// <summary> /// Runs the process. /// </summary> /// <returns>An awaitable task.</returns> public async override Task RunAsync() { try { while (true) { var r = await m_input.ReadAsync(); await Task.WhenAll( m_outputA.WriteAsync(r), m_outputB.WriteAsync(r) ); } } catch (RetiredException) { m_input.Retire(); m_outputA.Retire(); m_outputB.Retire(); } }
/// <summary> /// A process that spawns a new set of processes /// when a number is received. /// By inserting a NoMultiples into the chain, /// it is guaranteed that no numbers that are divisible /// with any number in the chain can be retrieved by the /// Sieve. /// </summary> /// <returns>The awaitable task that represents the process</returns> /// <param name="input">The channel to read numbers from</param> /// <param name="output">The channel to write numbers to</param> private static async Task RunSieveAsync(IReadChannel <long> input, IWriteChannel <long> output) { var chan = ChannelManager.CreateChannel <long>(); try { var n = await input.ReadAsync(); await output.WriteAsync(n); await Task.WhenAll( RunNoMultiplesAsync(n, input, chan), RunSieveAsync(chan, output) ); } catch (RetiredException) { chan.Retire(); input.Retire(); output.Retire(); } }
/// <summary> /// Runs the delta process, which copies the value it reads onto two different channels /// </summary> /// <param name="chan_read">The channel to read from</param> /// <param name="chan_a">The channel to write to</param> /// <param name="chan_b">The channel to write to</param> private static async void RunDeltaAlt(IReadChannel <T> chan_read, IWriteChannel <T> chan_a, IWriteChannel <T> chan_b) { try { while (true) { var value = await chan_read.ReadAsync(); var offer = new SingleOffer <T>(); await Task.WhenAll( chan_a.WriteAsync(value), chan_b.WriteAsync(value, CoCoL.Timeout.Infinite, offer) ); } } catch (RetiredException) { chan_read.Retire(); chan_a.Retire(); chan_b.Retire(); } }
/// <summary> /// The runner helper method that calls the abstract request method /// </summary> /// <returns>An awaitable task</returns> protected Task RunAsync(IReadChannel <bool> reqchan, IWriteChannel <RequestResult> respchan) { return(AutomationExtensions.RunTask( new { reqchan, respchan }, async _ => { while (await reqchan.ReadAsync()) { var start = DateTime.Now; try { var resp = await PeformRequestAsync(); await respchan.WriteAsync(new RequestResult() { Started = start, Finished = DateTime.Now, Failed = m_expectedresponse != null && m_expectedresponse != resp }); } catch (System.Exception ex) { await respchan.WriteAsync(new RequestResult() { Started = start, Finished = DateTime.Now, Failed = true, Exception = ex }); if (m_options.Verbose) { Console.WriteLine(ex.Message); } } } })); }
/// <summary> /// Reads the channel asynchronously /// </summary> /// <param name="self">The channel to read from</param> /// <typeparam name="T">The channel data type parameter.</typeparam> /// <returns>The value read from the channel</returns> public static Task <T> ReadAsync <T>(this IReadChannel <T> self) { return(self.ReadAsync(Timeout.Infinite, null)); }
/// <summary> /// Runs a single peer connection, using the IPC link /// </summary> /// <returns>An awaitable task.</returns> /// <param name="self">This peer's information</param> /// <param name="remote">The remote peer's information</param> /// <param name="connecthandler">The method used to obtain the connection.</param> /// <param name="input">The channel for reading requests.</param> /// <param name="maxparallel">The maximum number of parallel handlers</param> private static async Task RunSingleConnection(PeerInfo self, PeerInfo remote, Func <Task <Stream> > connecthandler, IReadChannel <ConnectionRequest> input, int maxparallel) { // Get the local handler for remote requests var remotehandler = Channels.RemoteRequests.Get(); LeanIPC.IPCPeer connection = null; try { if (connecthandler == null) { throw new ArgumentNullException(nameof(connecthandler)); } if (input == null) { throw new ArgumentNullException(nameof(input)); } log.Debug($"Setting up connection to {remote?.Key}"); // Connect to the remote peer connection = new LeanIPC.IPCPeer(await connecthandler()); // Setup a handler for remote requests, that forwards responses from the remote handler connection.AddUserTypeHandler <Protocol.Request>( async(id, req) => { await connection.SendResponseAsync(id, (await remotehandler.SendConnectionRequestAsync(null, null, id, req)).Response); return(true); } ); var mainTask = connection.RunMainLoopAsync(self != remote); Key targetKey = null; // Grab a connection to update the routing table automatically var routingrequests = Channels.RoutingTableRequests.Get(); log.Debug($"Peer connection running {self.Key}, {self.Address}"); using (var tp = new TaskPool <ConnectionRequest>(maxparallel, (t, ex) => log.Warn("Unexpected error handling request", ex))) while (true) { log.Debug($"Peer connection is waiting for request ..."); // Get either a local or a remote request var req = await input.ReadAsync(); log.Debug($"Peer connection got request, handling on taskpool ..."); await tp.Run(req, () => { log.Debug($"Peer connection is forwarding a local {req.Request.Operation} request to the remote"); return(Task.Run(async() => { ConnectionResponse res; try { var p = await connection.SendAndWaitAsync <Protocol.Request, Protocol.Response>(req.Request); if (targetKey == null) { // Record the target key targetKey = p.Self.Key; if (remote == null || remote.Key == null) { remote = new PeerInfo(p.Self.Key, remote.Address); } // Write a registration request to the broker await Channels.ConnectionBrokerRegistrations.Get().WriteAsync( new ConnectionRegistrationRequest() { IsTerminate = false, UpdateRouting = true, Peer = remote } ); log.Debug($"Registering peer in routing table: {remote.Key} {remote.Address} ..."); await routingrequests.AddPeerAsync(remote.Key, remote); } if (p.Peers != null) { log.Debug($"Registering {p.Peers.Count} peers with the routing table ..."); foreach (var peer in p.Peers) { await routingrequests.AddPeerAsync(peer.Key, peer); } log.Debug($"Registered {p.Peers.Count} peers with the routing table"); } res = new ConnectionResponse() { Key = p.Self.Key, Response = p }; } catch (Exception ex) { log.Warn($"Failed to get result, sending error response", ex); res = new ConnectionResponse() { Key = targetKey, Exception = ex }; log.Warn($"Killing peer due to the previous exception"); await input.RetireAsync(); } if (req.Response != null) { try { await req.Response.WriteAsync(res); } catch (Exception ex) { log.Warn("Failed to send response", ex); } } })); }); } } finally { await remotehandler.RetireAsync(); if (connection != null) { try { await connection.ShutdownAsync(); } catch (Exception ex) { log.Warn("Failed to shut down IPC Peer", ex); } } // Write a registration request to the broker await Channels.ConnectionBrokerRegistrations.Get().WriteAsync( new ConnectionRegistrationRequest() { IsTerminate = false, UpdateRouting = false, Peer = remote } ); } }
/// <summary> /// Runs the tick collector process which measures the network performance /// </summary> /// <returns>The awaitable tick collector task.</returns> /// <param name="chan">The tick channel.</param> /// <param name="stop">The channel used to shut down the network.</param> private static async Task RunTickCollectorAsync(IReadChannel <T> chan, IChannel <T> stop, bool stop_after_tickcount) { var tickcount = 0; var rounds = 0; //Initialize await chan.ReadAsync(); var a_second = TimeSpan.FromSeconds(1).Ticks; //Warm up Console.WriteLine("Warming up ..."); DateTime m_last = DateTime.Now; while (await chan.ReadAsync() != 0) { if ((DateTime.Now - m_last).Ticks > a_second) { break; } } //Measuring Console.WriteLine("Measuring!"); var measure_span = TimeSpan.FromSeconds(5).Ticks; m_last = DateTime.Now; try { while (await chan.ReadAsync() != 0) { tickcount++; bool round_complete; if (stop_after_tickcount) { round_complete = tickcount >= Config.Ticks; } else { round_complete = (DateTime.Now - m_last).Ticks >= measure_span; } if (round_complete) { var duration = DateTime.Now - m_last; Console.WriteLine("Got {0} ticks in {1} seconds, speed is {2} rounds/s ({3} msec/comm)", tickcount, duration, tickcount / duration.TotalSeconds, duration.TotalMilliseconds / ((tickcount) * Config.Processes)); Console.WriteLine("Time per iteration: {0} microseconds", (duration.TotalMilliseconds * 1000) / tickcount); Console.WriteLine("Time per communication: {0} microseconds", (duration.TotalMilliseconds * 1000) / tickcount / 4); tickcount = 0; m_last = DateTime.Now; // For shutdown, we retire the initial channel if (++rounds >= Config.MeasureCount) { stop.Retire(); } } } } catch (RetiredException) { chan.Retire(); } }
/// <summary> /// Reads the channel asynchronously. /// </summary> /// <returns>The task for awaiting completion.</returns> /// <param name="self">The channel to read.</param> /// <param name="timeout">The read timeout.</param> public static Task <T> ReadAsync <T>(this IReadChannel <T> self, TimeSpan timeout) { return(self.ReadAsync(new TimeoutOffer(timeout))); }
/// <summary> /// Reads the channel asynchronously. /// </summary> /// <returns>The task for awaiting completion.</returns> /// <param name="self">The channel to read.</param> /// <param name="cancelToken">The cancellation token</param> public static Task <T> ReadAsync <T>(this IReadChannel <T> self, CancellationToken cancelToken) { return(self.ReadAsync(new CancellationOffer(cancelToken))); }
/// <summary> /// Reads the channel asynchronously. /// </summary> /// <returns>The task for awaiting completion.</returns> /// <param name="self">The channel to read.</param> /// <param name="timeout">The read timeout.</param> /// <param name="cancelToken">The cancellation token</param> public static Task <T> ReadAsync <T>(this IReadChannel <T> self, TimeSpan timeout, CancellationToken cancelToken) { return(self.ReadAsync(new TimeoutOffer(timeout, cancelToken))); }