internal static bool TestConsumeMessage <T>(ISourceBlock <T> source) { bool consumed; source.ConsumeMessage(new DataflowMessageHeader(-99), new ActionBlock <T>(i => { }), out consumed); if (consumed) { Console.WriteLine("ConsumeMessage failed, didn't return messageConsumed==false for a unresrved msg"); return(false); } // test consume the correct message with different target var mres = new ManualResetEventSlim(false); var offeredMessage = default(DataflowMessageHeader); var target1 = new TransparentBlock <T>((msg) => { offeredMessage = msg; mres.Set(); }, false); source.LinkTo(target1); mres.Wait(); if (!source.ReserveMessage(offeredMessage, target1)) { Console.WriteLine("ReserveMessage failed, returned false"); return(false); } //exclude writeOnce and broadCast because they don't respect reservation to the target if (!(source is WriteOnceBlock <T> || source is BroadcastBlock <T>)) { //define another target var target2 = new TransparentBlock <T>(null); source.ConsumeMessage(offeredMessage, target2, out consumed); if (consumed) { Console.WriteLine("ConsumeMessage failed, a different target succeeded to consume the message that it doesn't own"); return(false); } } //same target different msg source.ConsumeMessage(new DataflowMessageHeader(-99), target1, out consumed); if (consumed) { Console.WriteLine("ConsumeMessage failed, the target succeeded to consume a differnt msg"); return(false); } //same target, same message source.ConsumeMessage(offeredMessage, target1, out consumed); if (!consumed) { Console.WriteLine("ConsumeMessage failed, the target failed to consume the reserved msg"); return(false); } return(true); }
internal static bool TestArgumentsExceptions <T>(ISourceBlock <T> source) { bool passed = true; var validMessageHeader = new DataflowMessageHeader(1); var invalidMessageHeader = default(DataflowMessageHeader); ITargetBlock <T> validTarget = new BufferBlock <T>(); ITargetBlock <T> invalidTarget = null; DataflowLinkOptions invalidLinkOptions = null; DataflowLinkOptions validLinkOptions = new DataflowLinkOptions(); bool consumed; Assert.Throws <ArgumentNullException>(() => source.ConsumeMessage(validMessageHeader, invalidTarget, out consumed)); Assert.Throws <ArgumentException>(() => source.ConsumeMessage(invalidMessageHeader, validTarget, out consumed)); Assert.Throws <ArgumentException>(() => source.ConsumeMessage(invalidMessageHeader, invalidTarget, out consumed)); Assert.Throws <ArgumentNullException>(() => source.ReserveMessage(validMessageHeader, invalidTarget)); Assert.Throws <ArgumentException>(() => source.ReserveMessage(invalidMessageHeader, validTarget)); Assert.Throws <ArgumentException>(() => source.ReserveMessage(invalidMessageHeader, invalidTarget)); Assert.Throws <ArgumentNullException>(() => source.ReleaseReservation(validMessageHeader, invalidTarget)); Assert.Throws <ArgumentException>(() => source.ReleaseReservation(invalidMessageHeader, validTarget)); Assert.Throws <ArgumentException>(() => source.ReleaseReservation(invalidMessageHeader, invalidTarget)); Assert.Throws <ArgumentNullException>(() => source.LinkTo(invalidTarget)); Assert.Throws <ArgumentNullException>(() => source.LinkTo(invalidTarget, validLinkOptions)); Assert.Throws <ArgumentNullException>(() => source.LinkTo(validTarget, invalidLinkOptions)); Assert.Throws <ArgumentNullException>(() => source.LinkTo(invalidTarget, invalidLinkOptions)); return(passed); }
public DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock <TInput> source, Boolean consumeToAccept) { DataflowMessageStatus returnValue; lock (_m_incomingLock) { if (_m_alwaysAccept) { bool consumed = !consumeToAccept; var acceptedMessage = (source != null && consumeToAccept) ? source.ConsumeMessage(messageHeader, this, out consumed) : messageValue; _m_messages.Enqueue(messageValue); returnValue = DataflowMessageStatus.Accepted; } else { returnValue = DataflowMessageStatus.Declined; } } if (_m_action != null) { _m_action(messageHeader); } return(returnValue); }
public DataflowMessageStatus OfferMessage( DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock <TInput> source, bool consumeToAccept) { if (!messageHeader.IsValid) { throw new ArgumentException("The messageHeader is not valid.", "messageHeader"); } if (consumeToAccept && source == null) { throw new ArgumentException( "consumeToAccept may only be true if provided with a non-null source.", "consumeToAccept"); } if (consumeToAccept) { if (!source.ReserveMessage(messageHeader, this)) { return(DataflowMessageStatus.NotAvailable); } bool consummed; source.ConsumeMessage(messageHeader, this, out consummed); if (!consummed) { return(DataflowMessageStatus.NotAvailable); } } return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, ResourceEvent <TResource> resourceEvent, ISourceBlock <ResourceEvent <TResource> > source, bool consumeToAccept) { if (_isCompleting) { return(DataflowMessageStatus.DecliningPermanently); } if (consumeToAccept) { resourceEvent = source.ConsumeMessage(messageHeader, this, out var consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } if (resourceEvent.EventFlags.HasFlag(EventTypeFlags.ResetEmpty) || resourceEvent.Value == null) { return(DataflowMessageStatus.Declined); } lock (_lock) { // decline any syncs if we're already queued up to process this resource if (resourceEvent.EventFlags.HasFlag(EventTypeFlags.Sync) && _items.ContainsKey(_keyFunc(resourceEvent.Value))) { return(DataflowMessageStatus.Declined); } QueueActionLocked(resourceEvent); } return(DataflowMessageStatus.Accepted); }
internal static void TestConsumeReserveReleaseArgumentsExceptions <T>(ISourceBlock <T> source) { DataflowMessageHeader validMessageHeader = new DataflowMessageHeader(1), invalidMessageHeader = default(DataflowMessageHeader); ITargetBlock <T> validTarget = new BufferBlock <T>(), invalidTarget = null; bool consumed; Assert.Throws <ArgumentNullException>(() => source.ConsumeMessage(validMessageHeader, invalidTarget, out consumed)); Assert.Throws <ArgumentException>(() => source.ConsumeMessage(invalidMessageHeader, validTarget, out consumed)); Assert.Throws <ArgumentException>(() => source.ConsumeMessage(invalidMessageHeader, invalidTarget, out consumed)); Assert.Throws <ArgumentNullException>(() => source.ReserveMessage(validMessageHeader, invalidTarget)); Assert.Throws <ArgumentException>(() => source.ReserveMessage(invalidMessageHeader, validTarget)); Assert.Throws <ArgumentException>(() => source.ReserveMessage(invalidMessageHeader, invalidTarget)); Assert.Throws <ArgumentNullException>(() => source.ReleaseReservation(validMessageHeader, invalidTarget)); Assert.Throws <ArgumentException>(() => source.ReleaseReservation(invalidMessageHeader, validTarget)); Assert.Throws <ArgumentException>(() => source.ReleaseReservation(invalidMessageHeader, invalidTarget)); }
public DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, T messageValue, ISourceBlock <T> source, bool consumeToAccept) { if (!IsOpen) { return(DataflowMessageStatus.Declined); } if (consumeToAccept) { bool messageConsumed; source.ConsumeMessage(messageHeader, this, out messageConsumed); if (!messageConsumed) { return(DataflowMessageStatus.Declined); } } toPropergate = messageValue; foreach (ITargetBlock <T> target in this.links) { target.OfferMessage(messageHeader, messageValue, this, true); } return(DataflowMessageStatus.Accepted); }
/// <summary> /// Consumes the message (request by other targets). /// </summary> /// <param name="messageHeader">The message header.</param> /// <param name="target">The target.</param> /// <param name="messageConsumed">if set to <c>true</c> [message consumed].</param> /// <returns></returns> public T ConsumeMessage( DataflowMessageHeader messageHeader, ITargetBlock <T> target, out bool messageConsumed) { T result = Source.ConsumeMessage(messageHeader, target, out messageConsumed); BlockInfo.PoolRequestCounters.Increment(messageConsumed); #region BlockInfo.PoolRequest.Add(...) var hookTarget = target as ITargetHook <T>; if (!(target is LinkHook <T>)) // optimization, in this case the like hook will handle the message { string targetName = string.Empty; if (hookTarget != null) { targetName = hookTarget.BlockInfo.Name; } var msg = new ConsumeTrace(messageHeader.Id, messageConsumed, BlockInfo.Name, targetName, result); BlockInfo.PoolRequest.Add(msg); } #endregion // BlockInfo.PoolRequest.Add(...) BlockInfo.Refresh(); return(result); }
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Targets/Member[@name="OfferMessage"]/*' /> DataflowMessageStatus ITargetBlock <T> .OfferMessage(DataflowMessageHeader messageHeader, T messageValue, ISourceBlock <T> source, Boolean consumeToAccept) { // Validate arguments if (!messageHeader.IsValid) { throw new ArgumentException(SR.Argument_InvalidMessageHeader, "messageHeader"); } if (source == null && consumeToAccept) { throw new ArgumentException(SR.Argument_CantConsumeFromANullSource, "consumeToAccept"); } Contract.EndContractBlock(); bool thisThreadReservedCompletion = false; lock (ValueLock) { // If we are declining messages, bail if (_decliningPermanently) { return(DataflowMessageStatus.DecliningPermanently); } // Consume the message from the source if necessary. We do this while holding ValueLock to prevent multiple concurrent // offers from all succeeding. if (consumeToAccept) { bool consumed; messageValue = source.ConsumeMessage(messageHeader, this, out consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } // Update the header and the value _header = Common.SingleMessageHeader; _value = messageValue; // We got what we needed. Start declining permanently. _decliningPermanently = true; // Reserve Completion if (!_completionReserved) { thisThreadReservedCompletion = _completionReserved = true; } } // Since this call to OfferMessage succeeded (and only one can ever), complete the block // (but asynchronously so as not to block the Post call while offering to // targets, running synchronous continuations off of the completion task, etc.) if (thisThreadReservedCompletion) { CompleteBlockAsync(exceptions: null); } return(DataflowMessageStatus.Accepted); }
static void SourceBlockTestInternal <T>(ISourceBlock <T> block) { var target = new BufferBlock <T> (); bool consumed; // invalid header AssertEx.Throws <ArgumentException> ( () => block.ConsumeMessage(new DataflowMessageHeader(), target, out consumed)); // header that wasn't sent by the block doesn't throw block.ConsumeMessage(new DataflowMessageHeader(1), target, out consumed); AssertEx.Throws <ArgumentNullException> ( () => block.ConsumeMessage(new DataflowMessageHeader(1), null, out consumed)); AssertEx.Throws <ArgumentException> ( () => block.ReserveMessage(new DataflowMessageHeader(), target)); // header that wasn't sent by the block doesn't throw block.ReserveMessage(new DataflowMessageHeader(1), target); AssertEx.Throws <ArgumentNullException> ( () => block.ReserveMessage(new DataflowMessageHeader(1), null)); AssertEx.Throws <ArgumentException> ( () => block.ReleaseReservation(new DataflowMessageHeader(), target)); AssertEx.Throws <ArgumentNullException>(() => block.LinkTo(null, new DataflowLinkOptions())); AssertEx.Throws <ArgumentNullException>(() => block.LinkTo(target, null)); }
private async void Consume(ISourceBlock <int> source, DataflowMessageHeader messageHeader) { await Task.Delay(3000); bool succeed; int i = source.ConsumeMessage(messageHeader, this, out succeed); lock (Program._sync) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("\tConsumed: {0}: Id = {1}, succeed = {2}", _name, messageHeader.Id, succeed); Console.ResetColor(); } }
internal static async Task TestReserveAndConsume <T>( ISourceBlock <T> block, bool reservationIsTargetSpecific = true) { bool consumed; block.ConsumeMessage(new DataflowMessageHeader(-99), new ActionBlock <T>(i => { }), out consumed); Assert.False(consumed); var tcs = new TaskCompletionSource <bool>(); var offeredMessage = default(DataflowMessageHeader); var target = new DelegatePropagator <T, T> { OfferMessageDelegate = (messageHeader, value, source, consumeToAccept) => { offeredMessage = messageHeader; tcs.TrySetResult(true); return(DataflowMessageStatus.Postponed); } }; block.LinkTo(target); await tcs.Task; Assert.True(block.ReserveMessage(offeredMessage, target)); // reserve the message if (reservationIsTargetSpecific) { block.ConsumeMessage(offeredMessage, new ActionBlock <T>(delegate { }), out consumed); // different target tries to consume Assert.False(consumed); } block.ConsumeMessage(new DataflowMessageHeader(-99), target, out consumed); // right target, wrong message Assert.False(consumed); block.ConsumeMessage(offeredMessage, target, out consumed); // right target, right message Assert.True(consumed); }
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Targets/Member[@name="OfferMessage"]/*' /> public DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, T messageValue, ISourceBlock <T> source, bool consumeToAccept) { // Validate arguments if (!messageHeader.IsValid) { throw new ArgumentException(SR.Argument_InvalidMessageHeader, nameof(messageHeader)); } if (source == null && consumeToAccept) { throw new ArgumentException(SR.Argument_CantConsumeFromANullSource, nameof(consumeToAccept)); } Contract.EndContractBlock(); lock (_sharedResources._incomingLock) { // If we've already stopped accepting messages, decline permanently if (_decliningPermanently || _sharedResources._decliningPermanently) { return(DataflowMessageStatus.DecliningPermanently); } // Consume the message from the source if necessary, and store the message if (consumeToAccept) { Debug.Assert(source != null, "We must have thrown if source == null && consumeToAccept == true."); bool consumed; messageValue = source.ConsumeMessage(messageHeader, this, out consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } _messages.Add(messageValue); // If this message makes a batch, notify the shared resources that a batch has been completed if (--_sharedResources._remainingItemsInBatch == 0) { _sharedResources._batchSizeReachedAction(); } return(DataflowMessageStatus.Accepted); } }
/// <summary>Implements the slow path for OfferMessage.</summary> /// <param name="messageHeader">The message header for the offered value.</param> /// <param name="messageValue">The offered value.</param> /// <param name="source">The source offering the message. This may be null.</param> /// <param name="consumeToAccept">true if we need to call back to the source to consume the message; otherwise, false if we can simply accept it directly.</param> /// <returns>The status of the message.</returns> private DataflowMessageStatus OfferMessage_Slow(DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock <TInput> source, bool consumeToAccept) { // If we're declining permanently, let the caller know. if (_decliningPermanently) { return(DataflowMessageStatus.DecliningPermanently); } // If the message header is invalid, throw. if (!messageHeader.IsValid) { throw new ArgumentException(SR.Argument_InvalidMessageHeader, "messageHeader"); } // If the caller has requested we consume the message using ConsumeMessage, do so. if (consumeToAccept) { if (source == null) { throw new ArgumentException(SR.Argument_CantConsumeFromANullSource, "consumeToAccept"); } bool consumed; messageValue = source.ConsumeMessage(messageHeader, _owningTarget, out consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } // See the "fast path" comments in Post _messages.Enqueue(messageValue); #if NET_4_0_ABOVE Interlocked.MemoryBarrier(); // ensure the read of _activeConsumer doesn't move up before the writes in Enqueue #else Thread.MemoryBarrier(); // ensure the read of _activeConsumer doesn't move up before the writes in Enqueue #endif if (_activeConsumer == null) { ScheduleConsumerIfNecessary(isReplica: false); } return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage(ITargetBlock <TInput> target, DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock <TInput> source, bool consumeToAccept) { if (!messageHeader.IsValid) { return(DataflowMessageStatus.Declined); } if (messageQueue.IsAddingCompleted) { return(DataflowMessageStatus.DecliningPermanently); } if (consumeToAccept) { bool consummed; if (!source.ReserveMessage(messageHeader, target)) { return(DataflowMessageStatus.NotAvailable); } messageValue = source.ConsumeMessage(messageHeader, target, out consummed); if (!consummed) { return(DataflowMessageStatus.NotAvailable); } } try { messageQueue.Add(messageValue); } catch (InvalidOperationException) { // This is triggered either if the underlying collection didn't accept the item // or if the messageQueue has been marked complete, either way it corresponds to a false return(DataflowMessageStatus.DecliningPermanently); } EnsureProcessing(); VerifyCompleteness(); return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, TOutput messageValue, ISourceBlock <TOutput> source, bool consumeToAccept) { if (!messageHeader.IsValid) { return(DataflowMessageStatus.Declined); } if (consumeToAccept) { bool consummed; if (!source.ReserveMessage(messageHeader, this)) { return(DataflowMessageStatus.NotAvailable); } messageValue = source.ConsumeMessage(messageHeader, this, out consummed); if (!consummed) { return(DataflowMessageStatus.NotAvailable); } } ReceivedValue = messageValue; completion.TrySetResult(messageValue); Thread.MemoryBarrier(); waitHandle.Set(); /* We do the unlinking here so that we don't get called twice */ if (linkBridge != null) { linkBridge.Dispose(); linkBridge = null; } return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage( DataflowMessageHeader messageHeader, T messageValue, ISourceBlock <T> source, bool consumeToAccept) { if (!IsOpen) { return(DataflowMessageStatus.Declined); } if (consumeToAccept) { source.ConsumeMessage(messageHeader, this, out var messageConsumed); if (!messageConsumed) { return(DataflowMessageStatus.Declined); } } _toPropergate = messageValue; _links.ForEach(target => target.OfferMessage(messageHeader, messageValue, this, true)); return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage( DataflowMessageHeader messageHeader, TSource messageValue, ISourceBlock <TSource> source, bool consumeToAccept) { if (consumeToAccept) { if (!source.ReserveMessage(messageHeader, this)) { return(DataflowMessageStatus.NotAvailable); } bool consumed; messageValue = source.ConsumeMessage(messageHeader, this, out consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } observer.OnNext(messageValue); return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage( DataflowMessageHeader messageHeader, TMessage messageValue, ISourceBlock <TMessage> source, bool consumeToAccept) { if (!chooserBlock.canAccept) { return(DataflowMessageStatus.DecliningPermanently); } bool lockTaken = false; try { chooserBlock.messageLock.Enter(ref lockTaken); if (!chooserBlock.canAccept) { return(DataflowMessageStatus.DecliningPermanently); } if (consumeToAccept) { bool consummed; messageValue = source.ConsumeMessage(messageHeader, this, out consummed); if (!consummed) { return(DataflowMessageStatus.NotAvailable); } } chooserBlock.canAccept = false; } finally { if (lockTaken) { chooserBlock.messageLock.Exit(); } } chooserBlock.MessageArrived(index, action, messageValue); return(DataflowMessageStatus.Accepted); }
public DataflowMessageStatus OfferMessage( DataflowMessageHeader messageHeader, TOutput messageValue, ISourceBlock <TOutput> source, bool consumeToAccept) { if (!messageHeader.IsValid) { return(DataflowMessageStatus.Declined); } if (completion.Task.Status != TaskStatus.WaitingForActivation) { return(DataflowMessageStatus.DecliningPermanently); } lock (completion) { if (completion.Task.Status != TaskStatus.WaitingForActivation) { return(DataflowMessageStatus.DecliningPermanently); } if (consumeToAccept) { bool consummed; if (!source.ReserveMessage(messageHeader, this)) { return(DataflowMessageStatus.NotAvailable); } messageValue = source.ConsumeMessage(messageHeader, this, out consummed); if (!consummed) { return(DataflowMessageStatus.NotAvailable); } } completion.TrySetResult(messageValue); } CompletionSet(); return(DataflowMessageStatus.Accepted); }
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Targets/Member[@name="OfferMessage"]/*' /> internal DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock <TInput> source, bool consumeToAccept) { // Validate arguments if (!messageHeader.IsValid) { throw new ArgumentException(SR.Argument_InvalidMessageHeader, nameof(messageHeader)); } if (source == null && consumeToAccept) { throw new ArgumentException(SR.Argument_CantConsumeFromANullSource, nameof(consumeToAccept)); } lock (IncomingLock) { // If we shouldn't be accepting more messages, don't. if (_decliningPermanently) { CompleteBlockIfPossible(); return(DataflowMessageStatus.DecliningPermanently); } // We can directly accept the message if: // 1) we are not bounding, OR // 2) we are bounding AND there is room available AND there are no postponed messages AND no messages are currently being transfered to the input queue. // (If there were any postponed messages, we would need to postpone so that ordering would be maintained.) // (Unlike all other blocks, TargetCore can accept messages while processing, because // input message IDs are properly assigned and the correct order is preserved.) if (_boundingState == null || (_boundingState.OutstandingTransfers == 0 && _boundingState.CountIsLessThanBound && _boundingState.PostponedMessages.Count == 0)) { // Consume the message from the source if necessary if (consumeToAccept) { Debug.Assert(source != null, "We must have thrown if source == null && consumeToAccept == true."); bool consumed; messageValue = source.ConsumeMessage(messageHeader, _owningTarget, out consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } // Assign a message ID - strictly sequential, no gaps. // Once consumed, enqueue the message with its ID and kick off asynchronous processing. long messageId = _nextAvailableInputMessageId.Value++; Debug.Assert(messageId != Common.INVALID_REORDERING_ID, "The assigned message ID is invalid."); if (_boundingState != null) { _boundingState.CurrentCount += 1; // track this new item against our bound } _messages.Enqueue(new KeyValuePair <TInput, long>(messageValue, messageId)); ProcessAsyncIfNecessary(); return(DataflowMessageStatus.Accepted); } // Otherwise, we try to postpone if a source was provided else if (source != null) { Debug.Assert(_boundingState != null && _boundingState.PostponedMessages != null, "PostponedMessages must have been initialized during construction in non-greedy mode."); // Store the message's info and kick off asynchronous processing _boundingState.PostponedMessages.Push(source, messageHeader); ProcessAsyncIfNecessary(); return(DataflowMessageStatus.Postponed); } // We can't do anything else about this message return(DataflowMessageStatus.Declined); } }
/// <include file='XmlDocs/CommonXmlDocComments.xml' path='CommonXmlDocComments/Targets/Member[@name="OfferMessage"]/*' /> DataflowMessageStatus ITargetBlock <T> .OfferMessage(DataflowMessageHeader messageHeader, T messageValue, ISourceBlock <T> source, Boolean consumeToAccept) { // Validate arguments if (!messageHeader.IsValid) { throw new ArgumentException(SR.Argument_InvalidMessageHeader, nameof(messageHeader)); } if (source == null && consumeToAccept) { throw new ArgumentException(SR.Argument_CantConsumeFromANullSource, nameof(consumeToAccept)); } Contract.EndContractBlock(); lock (IncomingLock) { // If we've already stopped accepting messages, decline permanently if (_targetDecliningPermanently) { CompleteTargetIfPossible(); return(DataflowMessageStatus.DecliningPermanently); } // We can directly accept the message if: // 1) we are not bounding, OR // 2) we are bounding AND there is room available AND there are no postponed messages AND we are not currently processing. // (If there were any postponed messages, we would need to postpone so that ordering would be maintained.) // (We should also postpone if we are currently processing, because there may be a race between consuming postponed messages and // accepting new ones directly into the queue.) if (_boundingState == null || (_boundingState.CountIsLessThanBound && _boundingState.PostponedMessages.Count == 0 && _boundingState.TaskForInputProcessing == null)) { // Consume the message from the source if necessary if (consumeToAccept) { Debug.Assert(source != null, "We must have thrown if source == null && consumeToAccept == true."); bool consumed; messageValue = source.ConsumeMessage(messageHeader, this, out consumed); if (!consumed) { return(DataflowMessageStatus.NotAvailable); } } // Once consumed, pass it to the source _source.AddMessage(messageValue); if (_boundingState != null) { _boundingState.CurrentCount++; } return(DataflowMessageStatus.Accepted); } // Otherwise, we try to postpone if a source was provided else if (source != null) { Debug.Assert(_boundingState != null && _boundingState.PostponedMessages != null, "PostponedMessages must have been initialized during construction in bounding mode."); _boundingState.PostponedMessages.Push(source, messageHeader); return(DataflowMessageStatus.Postponed); } // We can't do anything else about this message return(DataflowMessageStatus.Declined); } }
public Ping ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <Ping> target, out bool messageConsumed) { return(_source.ConsumeMessage(messageHeader, target, out messageConsumed)); }
public TTarget ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <TTarget> target, out bool messageConsumed) => _output.ConsumeMessage(messageHeader, target, out messageConsumed);
public T ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <T> target, out bool messageConsumed) { return(actualSource.ConsumeMessage(messageHeader, predicateBlock, out messageConsumed)); }
public DataflowMessageStatus OfferMessage( DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock <TInput> source, bool consumeToAccept) { if (!messageHeader.IsValid) { throw new ArgumentException("The messageHeader is not valid.", "messageHeader"); } if (consumeToAccept && source == null) { throw new ArgumentException( "consumeToAccept may only be true if provided with a non-null source.", "consumeToAccept"); } if (MessageQueue.IsAddingCompleted || !CompHelper.CanRun) { return(DataflowMessageStatus.DecliningPermanently); } var full = options.BoundedCapacity != -1 && Thread.VolatileRead(ref itemCount) >= options.BoundedCapacity; if (!greedy || full) { if (source == null) { return(DataflowMessageStatus.Declined); } postponedMessages [source] = messageHeader; // necessary to avoid race condition DecreaseCount(0); if (!greedy && !full) { EnsureProcessing(true); } return(DataflowMessageStatus.Postponed); } // in this case, we need to use locking to make sure // we don't consume when we can't accept if (consumeToAccept && canAccept != null) { bool lockTaken = false; try { consumingLock.Enter(ref lockTaken); if (!canAcceptFromBefore && !canAccept()) { return(DataflowMessageStatus.DecliningPermanently); } bool consummed; messageValue = source.ConsumeMessage(messageHeader, Target, out consummed); if (!consummed) { canAcceptFromBefore = true; return(DataflowMessageStatus.NotAvailable); } canAcceptFromBefore = false; } finally { if (lockTaken) { consumingLock.Exit(); } } } else { if (consumeToAccept) { bool consummed; messageValue = source.ConsumeMessage(messageHeader, Target, out consummed); if (!consummed) { return(DataflowMessageStatus.NotAvailable); } } if (canAccept != null && !canAccept()) { return(DataflowMessageStatus.DecliningPermanently); } } try { MessageQueue.Add(messageValue); } catch (InvalidOperationException) { // This is triggered either if the underlying collection didn't accept the item // or if the messageQueue has been marked complete, either way it corresponds to a false return(DataflowMessageStatus.DecliningPermanently); } IncreaseCount(); EnsureProcessing(true); VerifyCompleteness(); return(DataflowMessageStatus.Accepted); }
public ISegment <IGeofencingSample> ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <ISegment <IGeofencingSample> > target, out bool messageConsumed) => _source.ConsumeMessage(messageHeader, target, out messageConsumed);
public T[] ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <T[]> targets, out bool messageConsumed) { return(_batchBlock.ConsumeMessage(messageHeader, targets, out messageConsumed)); }
TSplit ISourceBlock <TSplit> .ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <TSplit> target, out bool messageConsumed) { return(orderCapturer.ConsumeMessage(messageHeader, target, out messageConsumed)); }
public TOutput ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock <TOutput> target, out bool messageConsumed) { return(source.ConsumeMessage(messageHeader, target, out messageConsumed)); }