/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public async Task WriteAsync(T value, TimeSpan timeout, ITwoPhaseOffer offer) { var tcs = new TaskCompletionSource <bool>(); await NetworkConfig.TransmitRequestAsync(new PendingNetworkRequest(this, typeof(T), timeout == Timeout.Infinite ? new DateTime(0) : DateTime.Now + timeout, offer, tcs, value)); await tcs.Task; }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A two-phase offer, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <returns>The async.</returns> public async Task WriteAsync(T value, ITwoPhaseOffer offer) { var tcs = new TaskCompletionSource <bool>(); await NetworkConfig.TransmitRequestAsync(new PendingNetworkRequest(this, typeof(T), Timeout.InfiniteDateTime, offer, tcs, value)).ConfigureAwait(false); await tcs.Task.ConfigureAwait(false); }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> public async Task <T> ReadAsync(ITwoPhaseOffer offer) { var tcs = new TaskCompletionSource <T>(); await NetworkConfig.TransmitRequestAsync(new PendingNetworkRequest(this, typeof(T), Timeout.InfiniteDateTime, offer, tcs)).ConfigureAwait(false); return(await tcs.Task.ConfigureAwait(false)); }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public async Task <T> ReadAsync(TimeSpan timeout, ITwoPhaseOffer offer = null) { var tcs = new TaskCompletionSource <T>(); await NetworkConfig.TransmitRequestAsync(new PendingNetworkRequest(this, typeof(T), timeout == Timeout.Infinite ? new DateTime(0) : DateTime.Now + timeout, offer, tcs)); return(await tcs.Task); }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> public async Task <T> ReadAsync(ITwoPhaseOffer offer) { if (m_maxreads > 0) { using (await m_readlock.LockAsync()) { m_reads++; if (m_last_read_update > TimeSpan.TicksPerSecond) { m_reads = 0; m_last_read_update = DateTime.Now.Ticks; } // Check if there are too many in this period if (m_reads > m_maxreads) { // Prevent others from entering await Task.Delay(new TimeSpan(Math.Max(0, TimeSpan.TicksPerSecond - (DateTime.Now.Ticks - m_last_read_update)))).ConfigureAwait(false); // Clear our attempt m_reads = 1; m_last_read_update = DateTime.Now.Ticks; } } } return(await m_channel.ReadAsync(offer)); }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write</param> public async Task WriteAsync(T value, ITwoPhaseOffer offer) { if (m_maxwrites > 0) { using (await m_writelock.LockAsync()) { m_writes++; if (m_last_write_update > TimeSpan.TicksPerSecond) { m_writes = 0; m_last_write_update = DateTime.Now.Ticks; } // Check if there are too many in this period if (m_writes > m_maxwrites) { // Prevent others from entering await Task.Delay(new TimeSpan(Math.Max(0, TimeSpan.TicksPerSecond - (DateTime.Now.Ticks - m_last_write_update)))).ConfigureAwait(false); // Clear our attempt m_writes = 1; m_last_write_update = DateTime.Now.Ticks; } } } await m_channel.WriteAsync(value, offer); }
/// <summary> /// Initializes a new instance of the <see cref="CoCoL.Channel<T>.WriterEntry"/> struct. /// </summary> /// <param name="offer">The offer handler</param> /// <param name="callback">The callback method for reporting progress.</param> /// <param name="expires">The timeout value.</param> /// <param name="value">The value being written.</param> public WriterEntry(ITwoPhaseOffer offer, TaskCompletionSource <bool> callback, DateTime expires, T value) { Offer = offer; Source = callback; Expires = expires; Value = value; }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public async Task WriteAsync(T value, TimeSpan timeout, ITwoPhaseOffer offer = null) { m_writeQueue.Enqueue(m_parent.WriteAsync(value, timeout, offer)); while (m_writeQueue.Count > m_buffersize) { await m_writeQueue.Dequeue(); } }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public Task <T> ReadAsync(TimeSpan timeout, ITwoPhaseOffer offer = null) { var tg = m_target; if (tg == null) { throw new ObjectDisposedException(this.GetType().FullName); } return(((IReadChannel <T>)tg).ReadAsync(timeout, offer)); }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public Task WriteAsync(T value, TimeSpan timeout, ITwoPhaseOffer offer = null) { var tg = m_target; if (tg == null) { throw new ObjectDisposedException(this.GetType().FullName); } return(((IWriteChannel <T>)tg).WriteAsync(value, timeout, offer)); }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> public async Task WriteAsync(T value, ITwoPhaseOffer offer) { var start = DateTime.Now.Ticks; await m_channel.WriteAsync(value, offer); var waitticks = DateTime.Now.Ticks - start; m_minwritedelayticks = Math.Min(m_minwritedelayticks, waitticks); m_maxwritedelayticks = Math.Max(m_maxwritedelayticks, waitticks); m_writedelayticks += waitticks; m_writes++; }
/// <summary> /// Initializes a new instance of the <see cref="CoCoL.Network.PendingNetworkRequest"/> class for representing a read request. /// </summary> /// <param name="channel">The channel to communicate over.</param> /// <param name="channeldatatype">The datatype on the channel.</param> /// <param name="timeout">The timeout associated with the request.</param> /// <param name="offer">The two-phase offer, if any.</param> /// <param name="task">The <see cref="System.Threading.Tasks.TaskCompletionSource<T>"/> instance for signaling.</param> public PendingNetworkRequest(INamedItem channel, Type channeldatatype, DateTime timeout, ITwoPhaseOffer offer, object task) { ChannelID = channel.Name; AssociatedChannel = channel; ChannelDataType = channeldatatype; RequestID = Guid.NewGuid().ToString("N"); SourceID = NetworkConfig.SelfID; Timeout = timeout; Offer = offer; Task = task; RequestType = NetworkMessageType.ReadRequest; NoOffer = offer == null; }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> public async Task <T> ReadAsync(ITwoPhaseOffer offer) { var start = DateTime.Now.Ticks; var res = await m_channel.ReadAsync(offer); var waitticks = DateTime.Now.Ticks - start; m_minreaddelayticks = Math.Min(m_minreaddelayticks, waitticks); m_maxreaddelayticks = Math.Max(m_maxreaddelayticks, waitticks); m_readdelayticks += waitticks; m_reads++; return(res); }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public Task <T> ReadAsync(TimeSpan timeout, ITwoPhaseOffer offer = null) { if (offer != null) { throw new InvalidOperationException("LatencyHidingReader does not support offers"); } while (m_readQueue.Count < m_buffersize) { m_readQueue.Enqueue(m_parent.ReadAsync(timeout, offer)); } return(m_readQueue.Dequeue()); }
/// <summary> /// Writes the channel synchronously /// </summary> /// <param name="self">The channel to write.</param> /// <param name="value">The value to write.</param> /// <param name="offer">The two-phase offer.</param> public static void Write(this IUntypedChannel self, object value, ITwoPhaseOffer offer) { var res = WriteAsync(self, value, offer).WaitForTask(); if (res.Exception != null) { if (res.Exception.Flatten().InnerExceptions.Count == 1) { throw res.Exception.InnerException; } throw res.Exception; } else if (res.IsCanceled) { throw new OperationCanceledException(); } }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <returns>The async.</returns> public Task WriteAsync(T value, ITwoPhaseOffer offer = null) { return(WriteAsync(value, Timeout.Infinite, offer)); }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <returns>The async.</returns> public Task <T> ReadAsync(ITwoPhaseOffer offer = null) { return(ReadAsync(Timeout.Infinite, offer)); }
/// <summary> /// Writes the channel and returns the task /// </summary> /// <returns>The async task.</returns> /// <param name="channel">The channel to write to.</param> /// <param name="value">The value to write.</param> /// <param name="offer">The two-phase offer.</param> public Task WriteAsync(IUntypedChannel channel, object value, ITwoPhaseOffer offer) { return((channel as IWriteChannel <T>).WriteAsync((T)value, offer)); }
/// <summary> /// Reads from the channel and returns the task /// </summary> /// <returns>The async task.</returns> /// <param name="channel">The channel to read from.</param> /// <param name="offer">The two-phase offer.</param> /// <param name="timeout">The timeout value.</param> public async Task <object> ReadAsync(IUntypedChannel channel, TimeSpan timeout, ITwoPhaseOffer offer = null) { return(await(channel as IReadChannel <T>).ReadAsync(timeout, offer)); }
/// <summary> /// Reads from the channel and returns the task /// </summary> /// <returns>The async task.</returns> /// <param name="channel">The channel to read from.</param> /// <param name="offer">The two-phase offer.</param> public async Task <object> ReadAsync(IUntypedChannel channel, ITwoPhaseOffer offer) { return(await(channel as IReadChannel <T>).ReadAsync(offer)); }
/// <summary> /// Writes the channel and returns the task /// </summary> /// <returns>The async task.</returns> /// <param name="channel">The channel to write to.</param> /// <param name="value">The value to write.</param> /// <param name="offer">The two-phase offer.</param> /// <param name="timeout">The timeout value.</param> public Task WriteAsync(IUntypedChannel channel, object value, TimeSpan timeout, ITwoPhaseOffer offer = null) { return((channel as IWriteChannel <T>).WriteAsync((T)value, timeout, offer)); }
/// <summary> /// Reads the channel synchronously. /// </summary> /// <returns>The value read.</returns> /// <param name="self">The channel to read.</param> /// <param name="offer">The two-phase offer token.</param> public static object Read(this IUntypedChannel self, ITwoPhaseOffer offer) { return(WaitForTask <object>(ReadAsync(self, offer)).Result); }
/// <summary> /// Reads the channel asynchronously. /// </summary> /// <returns>The task for awaiting completion.</returns> /// <param name="self">The channel to read.</param> /// <param name="offer">The two-phase offer.</param> public static Task <object> ReadAsync(this IUntypedChannel self, ITwoPhaseOffer offer) { return(UntypedAccessMethods.CreateReadAccessor(self).ReadAsync(self, offer)); }
/// <summary> /// Initializes a new instance of the <see cref="CoCoL.Channel<T>.ReaderEntry"/> struct. /// </summary> /// <param name="offer">The offer handler</param> /// <param name="callback">The callback method for reporting progress.</param> /// <param name="expires">The timeout value.</param> public ReaderEntry(ITwoPhaseOffer offer, TaskCompletionSource <T> callback, DateTime expires) { Offer = offer; Source = callback; Expires = expires; }
/// <summary> /// Writes the channel asynchronously /// </summary> /// <returns>The task for awaiting completion.</returns> /// <param name="self">The channel to write.</param> /// <param name="offer">The two-phase offer.</param> /// <param name="value">The value to write.</param> public static Task WriteAsync(this IUntypedChannel self, object value, ITwoPhaseOffer offer) { return(UntypedAccessMethods.CreateWriteAccessor(self).WriteAsync(self, value, offer)); }
// Since this is just a marker, we do not implement any methods #region IReadChannel implementation /// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public Task <T> ReadAsync(TimeSpan timeout, ITwoPhaseOffer offer = null) { throw new NotImplementedException(); }
/// <summary> /// Registers a desire to read from the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a negative span to wait forever.</param> public async Task <T> ReadAsync(TimeSpan timeout, ITwoPhaseOffer offer = null) { var rd = new ReaderEntry(offer, new TaskCompletionSource <T>(), timeout.Ticks <= 0 ? Timeout.InfiniteDateTime : DateTime.Now + timeout); using (await m_asynclock.LockAsync()) { if (m_isRetired) { ThreadPool.QueueItem(() => rd.Source.SetException(new RetiredException())); return(await rd.Source.Task); } m_readerQueue.Add(rd); if (!await MatchReadersAndWriters(true, rd.Source.Task)) { System.Diagnostics.Debug.Assert(m_readerQueue[m_readerQueue.Count - 1].Source == rd.Source); // If this was a probe call, return a timeout now if (timeout.Ticks >= 0 && rd.Expires < DateTime.Now) { m_readerQueue.RemoveAt(m_readerQueue.Count - 1); ThreadPool.QueueItem(() => rd.Source.TrySetException(new TimeoutException())); } else { // Make room if we have too many if (m_maxPendingReaders > 0 && (m_readerQueue.Count - 1) >= m_maxPendingReaders) { switch (m_pendingReadersOverflowStrategy) { case QueueOverflowStrategy.FIFO: { var exp = m_readerQueue[0].Source; m_readerQueue.RemoveAt(0); ThreadPool.QueueItem(() => exp.TrySetException(new ChannelOverflowException())); } break; case QueueOverflowStrategy.LIFO: { var exp = m_readerQueue[m_readerQueue.Count - 2].Source; m_readerQueue.RemoveAt(m_readerQueue.Count - 2); ThreadPool.QueueItem(() => exp.TrySetException(new ChannelOverflowException())); } break; case QueueOverflowStrategy.Reject: default: { var exp = m_readerQueue[m_readerQueue.Count - 1].Source; m_readerQueue.RemoveAt(m_readerQueue.Count - 1); ThreadPool.QueueItem(() => exp.TrySetException(new ChannelOverflowException())); await rd.Source.Task; } return(await rd.Source.Task); } } // If we have expanded the queue with a new batch, see if we can purge old entries m_readerQueueCleanup = await PerformQueueCleanupAsync(m_readerQueue, true, m_readerQueueCleanup); if (rd.Expires != Timeout.InfiniteDateTime) { ExpirationManager.AddExpirationCallback(rd.Expires, () => ExpireItemsAsync().FireAndForget()); } } } } return(await rd.Source.Task); }
/// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a negative span to wait forever.</param> public async Task WriteAsync(T value, TimeSpan timeout, ITwoPhaseOffer offer = null) { var wr = new WriterEntry(offer, new TaskCompletionSource <bool>(), timeout.Ticks <= 0 ? Timeout.InfiniteDateTime : DateTime.Now + timeout, value); using (await m_asynclock.LockAsync()) { if (m_isRetired) { ThreadPool.QueueItem(() => wr.Source.SetException(new RetiredException())); await wr.Source.Task; return; } m_writerQueue.Add(wr); if (!await MatchReadersAndWriters(false, wr.Source.Task)) { System.Diagnostics.Debug.Assert(m_writerQueue[m_writerQueue.Count - 1].Source == wr.Source); // If we have a buffer slot to use if (m_writerQueue.Count <= m_bufferSize && m_retireCount < 0) { if (offer == null || await offer.OfferAsync(this)) { if (offer != null) { await offer.CommitAsync(this); } m_writerQueue[m_writerQueue.Count - 1] = new WriterEntry(null, null, Timeout.InfiniteDateTime, value); wr.Source.TrySetResult(true); } else { wr.Source.TrySetCanceled(); } } else { // If this was a probe call, return a timeout now if (timeout.Ticks >= 0 && wr.Expires < DateTime.Now) { m_writerQueue.RemoveAt(m_writerQueue.Count - 1); ThreadPool.QueueItem(() => wr.Source.SetException(new TimeoutException())); } else { // Make room if we have too many if (m_maxPendingWriters > 0 && (m_writerQueue.Count - m_bufferSize - 1) >= m_maxPendingWriters) { switch (m_pendingWritersOverflowStrategy) { case QueueOverflowStrategy.FIFO: { var exp = m_writerQueue[m_bufferSize].Source; m_writerQueue.RemoveAt(m_bufferSize); if (exp != null) { ThreadPool.QueueItem(() => exp.TrySetException(new ChannelOverflowException())); } } break; case QueueOverflowStrategy.LIFO: { var exp = m_writerQueue[m_writerQueue.Count - 2].Source; m_writerQueue.RemoveAt(m_writerQueue.Count - 2); if (exp != null) { ThreadPool.QueueItem(() => exp.TrySetException(new ChannelOverflowException())); } } break; case QueueOverflowStrategy.Reject: default: { var exp = m_writerQueue[m_writerQueue.Count - 1].Source; m_writerQueue.RemoveAt(m_writerQueue.Count - 1); if (exp != null) { ThreadPool.QueueItem(() => exp.TrySetException(new ChannelOverflowException())); } await wr.Source.Task; } return; } } // If we have expanded the queue with a new batch, see if we can purge old entries m_writerQueueCleanup = await PerformQueueCleanupAsync(m_writerQueue, true, m_writerQueueCleanup); if (wr.Expires != Timeout.InfiniteDateTime) { ExpirationManager.AddExpirationCallback(wr.Expires, () => ExpireItemsAsync().FireAndForget()); } } } } } await wr.Source.Task; return; }
// Since this is just a marker, we do not implement any methods #region IWriteChannel implementation /// <summary> /// Registers a desire to write to the channel /// </summary> /// <param name="offer">A callback method for offering an item, use null to unconditionally accept</param> /// <param name="value">The value to write to the channel.</param> /// <param name="timeout">The time to wait for the operation, use zero to return a timeout immediately if no items can be read. Use a /// negative span to wait forever.</param> /// <returns>The async.</returns> public Task WriteAsync(T value, TimeSpan timeout, ITwoPhaseOffer offer = null) { throw new NotImplementedException(); }
/// <summary> /// Writes the channel synchronously /// </summary> /// <param name="self">The channel to write.</param> /// <param name="value">The value to write.</param> /// <param name="timeout">The write timeout.</param> /// <param name="offer">The two-phase offer instance or null.</param> public static void Write(this IUntypedChannel self, object value, TimeSpan timeout, ITwoPhaseOffer offer = null) { var res = WriteAsync(self, value, timeout, offer).WaitForTask(); if (res.Exception != null) { if (res.Exception is AggregateException && ((AggregateException)res.Exception).Flatten().InnerExceptions.Count == 1) { throw ((AggregateException)res.Exception).InnerException; } throw res.Exception; } else if (res.IsCanceled) { throw new OperationCanceledException(); } }