/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="channels">The list of channels to call.</param> /// <param name="priority">The priority used to select channels, if multiple channels have a value that can be read.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <MultisetResult <T> > ReadFromAnyAsync <T>(MultiChannelPriority priority, params IReadChannel <T>[] channels) { return(ReadFromAnyAsync(null, channels.AsEnumerable(), Timeout.Infinite, priority)); }
/// <summary> /// Initializes a new instance of the <see cref="CoCoL.MultiChannelSetWrite<T>"/> class. /// </summary> /// <param name="priority">The priority to use when selecting a channel.</param> /// <param name="channels">The channels to consider.</param> public MultiChannelSetWrite(MultiChannelPriority priority, params IWriteChannel <T>[] channels) { m_channels = channels; m_sortedChannels = priority == MultiChannelPriority.Fair ? new SortedChannelList <IWriteChannel <T> >(channels) : null; m_priority = priority; }
/// <summary> /// Creates a multichannelset from a list of channels /// </summary> /// <returns>The multichannel set.</returns> /// <param name="channels">The channels to make the set from.</param> /// <param name="priority">The channel priority.</param> /// <typeparam name="T">The type of the channel.</typeparam> public static MultiChannelSetWrite <T> CreateSet <T>(this IEnumerable <IWriteChannel <T> > channels, MultiChannelPriority priority = MultiChannelPriority.Any) { return(new MultiChannelSetWrite <T>(channels, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="requests">The list of requests</param> /// <param name="priority">The priority used to select channels, if multiple channels have a value that can be read.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <MultisetRequest <T> > ReadOrWriteAnyAsync <T>(MultiChannelPriority priority, params MultisetRequest <T>[] requests) { return(ReadOrWriteAnyAsync(null, requests.AsEnumerable(), Timeout.Infinite, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="callback">The method to call when the read completes, or null.</param> /// <param name="requests">The list of requests</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> /// <typeparam name="T">The channel data type.</typeparam> private static Task <MultisetRequest <T> > ReadOrWriteAnyAsync <T>(this IEnumerable <MultisetRequest <T> > requests, Action <object> callback, TimeSpan timeout, MultiChannelPriority priority) { return(ReadOrWriteAnyAsync(callback, requests, timeout, priority)); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="value">The value to write to the channel.</param> /// <param name="channels">The list of channels to attempt to write.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <IWriteChannel <T> > WriteToAnyAsync <T>(T value, MultiChannelPriority priority, params IWriteChannel <T>[] channels) { return(WriteToAnyAsync(null, value, channels, Timeout.Infinite, priority)); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="value">The value to write to the channel.</param> /// <param name="channels">The list of channels to attempt to write.</param> /// <param name="timeout">The maximum time to wait for a channel to become ready for writing.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <IWriteChannel <T> > WriteToAnyAsync <T>(this IEnumerable <IWriteChannel <T> > channels, T value, TimeSpan timeout, MultiChannelPriority priority) { return(WriteToAnyAsync(null, value, channels, timeout, priority)); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="requests">The list of channels to attempt to write.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> public static Task <IUntypedChannel> WriteToAnyAsync(this IEnumerable <IMultisetRequestUntyped> requests, MultiChannelPriority priority) { return(WriteToAnyAsync(requests, Timeout.Infinite, priority)); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="requests">The list of channels to attempt to write.</param> /// <param name="timeout">The maximum time to wait for a channel to become ready for writing.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> public static async Task <IUntypedChannel> WriteToAnyAsync(this IEnumerable <IMultisetRequestUntyped> requests, TimeSpan timeout, MultiChannelPriority priority) { return((await ReadOrWriteAnyAsync(null, requests, timeout, priority)).Channel); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="callback">The method to call when the read completes, or null.</param> /// <param name="requests">The list of requests.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> public static async Task <IMultisetRequestUntyped> ReadFromAnyAsync(Action <object> callback, IEnumerable <IMultisetRequestUntyped> requests, TimeSpan timeout, MultiChannelPriority priority) { return(await ReadOrWriteAnyAsync(callback, requests, timeout, priority)); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="requests">The list of channels to attempt to write.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> public static Task <IUntypedChannel> WriteToAnyAsync(MultiChannelPriority priority, params IMultisetRequestUntyped[] requests) { return(WriteToAnyAsync(requests.AsEnumerable(), Timeout.Infinite, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="requests">The list of requests.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadFromAnyAsync(this IEnumerable <IMultisetRequestUntyped> requests, TimeSpan timeout, MultiChannelPriority priority) { return(ReadFromAnyAsync(null, requests, timeout, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="callback">The method to call after the read completes.</param> /// <param name="channels">The list of channels to attempt to read from.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadFromAnyAsync(Action <object> callback, IEnumerable <IUntypedChannel> channels, TimeSpan timeout, MultiChannelPriority priority) { return(ReadFromAnyAsync(callback, channels.Select(x => x.RequestRead()), timeout, priority)); }
/// <summary> /// Initializes a new instance of the <see cref="CoCoL.MultiChannelSetWrite<T>"/> class. /// </summary> /// <param name="priority">The priority to use when selecting a channel.</param> /// <param name="channels">The channels to consider.</param> public MultiChannelSetWrite(IEnumerable <IWriteChannel <T> > channels, MultiChannelPriority priority = MultiChannelPriority.Any) : this(priority, channels.ToArray()) { }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="channels">The list of channels to attempt to read from.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <MultisetResult <T> > ReadFromAnyAsync <T>(this IEnumerable <IReadChannel <T> > channels, TimeSpan timeout, MultiChannelPriority priority) { return(ReadFromAnyAsync(null, channels, timeout, priority)); }
/// <summary> /// Reads or writes any of the specified requests /// </summary> /// <param name="requests">The list of channels to call.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select channels, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadOrWriteAnyAsync(TimeSpan timeout, MultiChannelPriority priority, params IMultisetRequestUntyped[] requests) { return(ReadOrWriteAnyAsync(null, requests.AsEnumerable(), timeout, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="callback">The method to call when the read completes, or null.</param> /// <param name="channels">The list of channels to attempt to read from.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> /// <typeparam name="T">The channel data type.</typeparam> public static async Task <MultisetResult <T> > ReadFromAnyAsync <T>(Action <object> callback, IEnumerable <IReadChannel <T> > channels, TimeSpan timeout, MultiChannelPriority priority) { var res = await ReadOrWriteAnyAsync <T>(callback, channels.Select(x => x.RequestRead()), timeout, priority).ConfigureAwait(false); return(new MultisetResult <T>(res.Value, res.ReadChannel)); }
/// <summary> /// Reads or writes any of the specified requests /// </summary> /// <param name="requests">The list of channels to call.</param> /// <param name="priority">The priority used to select channels, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadOrWriteAnyAsync <T>(this IEnumerable <IMultisetRequestUntyped> requests, MultiChannelPriority priority) { return(ReadOrWriteAnyAsync(null, requests, Timeout.Infinite, priority)); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="value">The value to write to the channel.</param> /// <param name="channels">The list of channels to attempt to write.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <IWriteChannel <T> > WriteToAnyAsync <T>(T value, IEnumerable <IWriteChannel <T> > channels, MultiChannelPriority priority) { return(WriteToAnyAsync(null, value, channels, Timeout.Infinite, priority)); }
/// <summary> /// Reads or writes any of the specified requests /// </summary> /// <param name="callback">The method to call when the read completes, or null.</param> /// <param name="requests">The list of requests.</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadOrWriteAnyAsync(Action <object> callback, IEnumerable <IMultisetRequestUntyped> requests, TimeSpan timeout, MultiChannelPriority priority) { var tcs = new TaskCompletionSource <IMultisetRequestUntyped>(); // We only accept the first offer var offer = new SingleOffer <IMultisetRequestUntyped>(tcs, timeout == Timeout.Infinite ? Timeout.InfiniteDateTime : DateTime.Now + timeout); offer.SetCommitCallback(callback); switch (priority) { case MultiChannelPriority.Fair: throw new Exception(string.Format("Construct a {0} or {1} object to use fair multichannel operations", typeof(MultiChannelSetRead <>).Name, typeof(MultiChannelSetWrite <>).Name)); case MultiChannelPriority.Random: requests = MultiChannelAccess.Shuffle(requests); break; default: // Use the order the input has break; } // Keep a map of awaitable items var tasks = new Dictionary <Task, IMultisetRequestUntyped>(); // Then we register the intent to read from a channel in order foreach (var c in requests) { // Timeout is handled by offer instance if (c.IsRead) { tasks[c.Channel.ReadAsync(Timeout.Infinite, offer)] = c; } else { tasks[c.Channel.WriteAsync(c.Value, Timeout.Infinite, offer)] = c; } // Fast exit to avoid littering the channels if we are done if (offer.IsTaken) { break; } } offer.ProbePhaseComplete(); if (tasks.Count == 0) { tcs.TrySetException(new InvalidOperationException("List of channels was empty")); return(tcs.Task); } tasks.Keys.WhenAnyNonCancelled().ContinueWith(item => Task.Run(() => { if (item.IsCanceled) { tcs.TrySetCanceled(); return; } else if (item.IsFaulted) { tcs.TrySetException(item.Exception); return; } if (offer.AtomicIsFirst()) { var n = item.Result; // Figure out which item was found if (n.IsCanceled) { tcs.SetCanceled(); } else if (n.IsFaulted) { // Unwrap aggregate exceptions if (n.Exception is AggregateException && (n.Exception as AggregateException).Flatten().InnerExceptions.Count == 1) { tcs.SetException(n.Exception.InnerException); } else { tcs.SetException(n.Exception); } } else { var orig = tasks[n]; if (orig.IsRead) { orig.Value = ((Task <object>)n).Result; tcs.SetResult(orig); } else { orig.Value = null; tcs.SetResult(orig); } } } })); return(tcs.Task); }
/// <summary> /// Writes to any of the specified channels /// </summary> /// <param name="callback">The method to call when the write completes, or null.</param> /// <param name="value">The value to write to the channel.</param> /// <param name="channels">The list of channels to attempt to write.</param> /// <param name="timeout">The maximum time to wait for a channel to become ready for writing.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be written.</param> /// <typeparam name="T">The channel data type.</typeparam> public static async Task <IWriteChannel <T> > WriteToAnyAsync <T>(Action <object> callback, T value, IEnumerable <IWriteChannel <T> > channels, TimeSpan timeout, MultiChannelPriority priority) { return((await ReadOrWriteAnyAsync <T>(callback, channels.Select(x => x.RequestWrite(value)), timeout, priority).ConfigureAwait(false)).WriteChannel); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="channels">The list of channels to call.</param> /// <param name="priority">The priority used to select channels, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadFromAnyAsync(MultiChannelPriority priority, params IUntypedChannel[] channels) { return(ReadFromAnyAsync(null, channels.AsEnumerable(), Timeout.Infinite, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="requests">The list of requests</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> /// <typeparam name="T">The channel data type.</typeparam> public static Task <MultisetRequest <T> > ReadOrWriteAnyAsync <T>(this IEnumerable <MultisetRequest <T> > requests, TimeSpan timeout, MultiChannelPriority priority) { return(ReadOrWriteAnyAsync(null, requests, timeout, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="channels">The list of channels to call.</param> /// <param name="priority">The priority used to select channels, if multiple channels have a value that can be read.</param> public static Task <IMultisetRequestUntyped> ReadFromAnyAsync(this IEnumerable <IUntypedChannel> channels, MultiChannelPriority priority) { return(ReadFromAnyAsync(null, channels, Timeout.Infinite, priority)); }
/// <summary> /// Reads from any of the specified channels /// </summary> /// <param name="callback">The method to call when the read completes, or null.</param> /// <param name="requests">The list of requests</param> /// <param name="timeout">The maximum time to wait for a value to read.</param> /// <param name="priority">The priority used to select a channel, if multiple channels have a value that can be read.</param> /// <param name="cancelToken">The cancellation token</param> /// <typeparam name="T">The channel data type.</typeparam> private static Task <MultisetRequest <T> > ReadOrWriteAnyAsync <T>(Action <object> callback, IEnumerable <MultisetRequest <T> > requests, TimeSpan timeout, MultiChannelPriority priority, CancellationToken cancelToken = default(CancellationToken)) { // This method could also use the untyped version, // but using the type version is faster as there are no reflection // or boxing/typecasting required var tcs = new TaskCompletionSource <MultisetRequest <T> >(); // We only accept the first offer var offer = new SingleOffer <MultisetRequest <T> >(tcs, timeout == Timeout.Infinite ? Timeout.InfiniteDateTime : DateTime.Now + timeout, cancelToken); offer.SetCommitCallback(callback); switch (priority) { case MultiChannelPriority.Fair: throw new InvalidOperationException(string.Format("Construct a {0} or {1} object to use fair multichannel operations", typeof(MultiChannelSetRead <>).Name, typeof(MultiChannelSetWrite <>).Name)); case MultiChannelPriority.Random: requests = Shuffle(requests); break; default: // Use the order the input has break; } // Keep a map of awaitable items // and register the intent to read from a channel in order var tasks = new Dictionary <Task, MultisetRequest <T> >(); foreach (var c in requests) { // Timeout is handled by offer instance if (c.IsRead) { tasks[c.ReadChannel.ReadAsync(offer)] = c; } else { tasks[c.WriteChannel.WriteAsync(c.Value, offer)] = c; } // Fast exit to avoid littering the channels if we are done if (offer.IsTaken) { break; } } offer.ProbePhaseComplete(); if (tasks.Count == 0) { tcs.TrySetException(new InvalidOperationException("List of channels was empty")); return(tcs.Task); } tasks.Keys.WhenAnyNonCancelled().ContinueWith(item => Task.Run(() => { if (item.IsCanceled) { tcs.TrySetCanceled(); return; } else if (item.IsFaulted) { tcs.TrySetException(item.Exception); return; } var n = item.Result; if (offer.AtomicIsFirst()) { // Figure out which item was found if (n.IsCanceled) { tcs.SetCanceled(); } else if (n.IsFaulted) { // Unwrap aggregate exceptions if (n.Exception is AggregateException && (n.Exception as AggregateException).Flatten().InnerExceptions.Count == 1) { tcs.SetException(n.Exception.InnerException); } else { tcs.SetException(n.Exception); } } else { var orig = tasks[n]; if (orig.IsRead) { tcs.SetResult(new MultisetRequest <T>(((Task <T>)n).Result, orig.ReadChannel, null, true)); } else { tcs.SetResult(new MultisetRequest <T>(default(T), null, orig.WriteChannel, false)); } } } })); return(tcs.Task); }
/// <summary> /// Initializes a new instance of the <see cref="CoCoL.MultiChannelSetRead<T>"/> class. /// </summary> /// <param name="priority">The priority to use when selecting a channel.</param> /// <param name="channels">The channels to consider.</param> public MultiChannelSetRead(IEnumerable <IReadChannel <T> > channels, MultiChannelPriority priority) : this(priority, channels.ToArray()) { }