public OneToThreeSequencedThroughputTest()
            : base(Test_Disruptor, ITERATIONS, 7)
        {
            ThreadPool.SetMaxThreads(NUM_EVENT_PROCESSORS, NUM_EVENT_PROCESSORS);
            for (long i = 0; i < ITERATIONS; i++)
            {
                results[0] = Operation.Addition.Op(results[0], i);
                results[1] = Operation.Substraction.Op(results[1], i);
                results[2] = Operation.And.Op(results[2], i);
            }
            sequenceBarrier = ringBuffer.NewBarrier();

            handlers[0] = new ValueMutationEventHandler_v3(Operation.Addition);
            handlers[1] = new ValueMutationEventHandler_v3(Operation.Substraction);
            handlers[2] = new ValueMutationEventHandler_v3(Operation.And);

            batchEventProcessors[0] = new BatchEventProcessor <ValueEvent>(ringBuffer, sequenceBarrier, handlers[0]);
            batchEventProcessors[1] = new BatchEventProcessor <ValueEvent>(ringBuffer, sequenceBarrier, handlers[1]);
            batchEventProcessors[2] = new BatchEventProcessor <ValueEvent>(ringBuffer, sequenceBarrier, handlers[2]);

            ringBuffer.AddGatingSequences(
                batchEventProcessors[0].Sequence,
                batchEventProcessors[1].Sequence,
                batchEventProcessors[2].Sequence);
        }
        /// <summary>
        /// <see cref="IWaitStrategy.WaitFor"/>
        /// </summary>
        public long WaitFor(long sequence, Sequence cursor, ISequence dependentSequence, ISequenceBarrier barrier)
        {
            long startTime = 0;
            int counter = _spinTries;

            do
            {
                long availableSequence;
                if ((availableSequence = dependentSequence.Value) >= sequence)
                    return availableSequence;

                if (0 == --counter)
                {
                    if (0 == startTime)
                    {
                        startTime = GetSystemTimeTicks();
                    }
                    else
                    {
                        var timeDelta = GetSystemTimeTicks() - startTime;
                        if (timeDelta > _yieldTimeoutTicks)
                        {
                            return _fallbackStrategy.WaitFor(sequence, cursor, dependentSequence, barrier);
                        }

                        if (timeDelta > _spinTimeoutTicks)
                        {
                            Thread.Yield();
                        }
                    }
                    counter = _spinTries;
                }
            }
            while (true);
        }
        /// <summary>
        /// <see cref="IWaitStrategy.WaitFor"/>
        /// </summary>
        public long WaitFor(long sequence, Sequence cursor, ISequence dependentSequence, ISequenceBarrier barrier)
        {
            var timeSpan = _timeout;
            if (cursor.Value < sequence)
            {
                lock (_gate)
                {
                    while (cursor.Value < sequence)
                    {
                        barrier.CheckAlert();
                        if (!Monitor.Wait(_gate, timeSpan))
                        {
                            throw TimeoutException.Instance;
                        }
                    }
                }
            }

            long availableSequence;
            while ((availableSequence = dependentSequence.Value) < sequence)
            {
                barrier.CheckAlert();
            }

            return availableSequence;
        }
        /// <summary>
        /// Wait for the given sequence to be available
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">Ring buffer cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the <see cref="IEventProcessor"/> is waiting on.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            var availableSequence = cursor.Value; // volatile read
            if (availableSequence < sequence)
            {
                Monitor.Enter(_gate);
                try
                {
                    while ((availableSequence = cursor.Value) < sequence) // volatile read
                    {
                        barrier.CheckAlert();
                        Monitor.Wait(_gate);
                    }
                }
                finally
                {
                    Monitor.Exit(_gate);
                }
            }

            if (dependents.Length != 0)
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                }
            }

            return availableSequence;
        }
        /// <summary>
        /// Wait for the given sequence to be available
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">Ring buffer cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the <see cref="IEventProcessor"/> is waiting on.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            long availableSequence;
            var spinWait = default(SpinWait);

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();
                    if (spinWait.Count > 5000)
                        break;
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();
                    if (spinWait.Count > 5000)
                        break;
                }
            }

            return availableSequence;
        }
 public Lite_Timeout_Blocking_Wait_Strategy_Test()
 {
     _barrier   = new DummySequenceBarrier();
     _strategy  = new LiteTimeoutBlockingWaitStrategy(TimeoutMilliseconds);
     _cursor    = new Sequence(5);
     _dependent = _cursor;
 }
        /// <summary>
        /// <see cref="IWaitStrategy.WaitFor"/>.
        /// </summary>
        public long WaitFor(long sequence, Sequence cursor, ISequence dependentSequence, ISequenceBarrier barrier)
        {
            var milliseconds = _timeoutInMilliseconds;

            long availableSequence;
            if (cursor.Value < sequence)
            {
                lock (_lock)
                {
                    while (cursor.Value < sequence)
                    {
                        Interlocked.Exchange(ref _signalNeeded, 1);

                        barrier.CheckAlert();

                         if (!Monitor.Wait(_lock, milliseconds))
                        {
                            throw TimeoutException.Instance;
                        }
                    }
                }
            }

            while ((availableSequence = dependentSequence.Value) < sequence)
            {
                barrier.CheckAlert();
            }

            return availableSequence;
        }
示例#8
0
        /// <summary>
        /// Wait for the given sequence to be available
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">Ring buffer cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the <see cref="IEventProcessor"/> is waiting on.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            long availableSequence;
            var  spinWait = default(SpinWait);

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();
                    if (spinWait.Count > 5000)
                    {
                        break;
                    }
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();
                    if (spinWait.Count > 5000)
                    {
                        break;
                    }
                }
            }

            return(availableSequence);
        }
示例#9
0
            public long WaitOnLock(long sequence,
                                   Sequence cursorSequence,
                                   Sequence dependentSequence, ISequenceBarrier barrier, TimeSpan timeOut)
            {
                var availableSequence = cursorSequence.Value; // volatile read

                if (availableSequence < sequence)
                {
                    Monitor.Enter(_gate);
                    try
                    {
                        ++_numWaiters;
                        while ((availableSequence = cursorSequence.Value) < sequence) // volatile read
                        {
                            barrier.CheckAlert();
                            Monitor.Wait(_gate, timeOut);
                        }
                    }
                    finally
                    {
                        --_numWaiters;
                        Monitor.Exit(_gate);
                    }
                }
                while ((availableSequence = dependentSequence.Value) < sequence)
                {
                    barrier.CheckAlert();
                }
                return(availableSequence);
            }
 /// <summary>
 ///  Construct a <see cref="IBatchEventProcessor{TEvent}"/> that will automatically track the progress by updating its sequence when the <see cref="IEventHandler{TEvent}.OnEvent(TEvent,long,bool)"/> method returns.
 /// </summary>
 /// <param name="dataProvider">to which events are published.</param>
 /// <param name="sequenceBarrier">on which it is waiting.</param>
 /// <param name="eventHandler">is the delegate to which events are dispatched.</param>
 public BatchEventProcessor(
     IDataProvider <TEvent> dataProvider,
     ISequenceBarrier sequenceBarrier,
     IEventHandler <TEvent> eventHandler)
     : this(dataProvider, sequenceBarrier, eventHandler, null)
 {
 }
示例#11
0
        public void SetUp()
        {
            _ringBuffer = ValueRingBuffer <StubValueEvent> .CreateMultiProducer(() => new StubValueEvent(-1), 32);

            _sequenceBarrier = _ringBuffer.NewBarrier();
            _ringBuffer.AddGatingSequences(new NoOpEventProcessor <StubValueEvent>(_ringBuffer).Sequence);
        }
示例#12
0
        internal EventHandlerGroup <T> CreateEventProcessors(IEventProcessor[] barrierEventProcessors,
                                                             IEventHandler <T>[] eventHandlers, long startSequence = Sequencer.InitialCursorValue)
        {
            CheckNotStarted();

            var createdEventProcessors = new IEventProcessor[eventHandlers.Length];
            ISequenceBarrier barrier   = _ringBuffer.NewBarrier(Util.GetSequencesFor(barrierEventProcessors));

            for (int i = 0; i < eventHandlers.Length; i++)
            {
                var eventHandler = eventHandlers[i];

                var batchEventProcessor = new BatchEventProcessor <T>(_ringBuffer, barrier, eventHandler, startSequence);

                if (_exceptionHandler != null)
                {
                    batchEventProcessor.SetExceptionHandler(_exceptionHandler);
                }

                _eventProcessorRepository.Add(batchEventProcessor, eventHandler, barrier);
                createdEventProcessors[i] = batchEventProcessor;
            }

            if (createdEventProcessors.Length > 0)
            {
                _eventProcessorRepository.UnmarkEventProcessorsAsEndOfChain(barrierEventProcessors);
            }

            return(new EventHandlerGroup <T>(this, _eventProcessorRepository, createdEventProcessors));
        }
示例#13
0
        /// <summary>
        /// Wait for the given sequence to be available with a timeout specified.
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the processor is waiting on.</param>
        /// <param name="timeout">timeout value to abort after.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        /// <exception cref="AlertException">AlertException if the status of the Disruptor has changed.</exception>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier, TimeSpan timeout)
        {
            long availableSequence;
            var  spinWait = new SpinWait();
            var  sw       = Stopwatch.StartNew();

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();

                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();

                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }

            return(availableSequence);
        }
        /// <summary>
        /// Wait for the given sequence to be available with a timeout specified.
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the processor is waiting on.</param>
        /// <param name="timeout">timeout value to abort after.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        /// <exception cref="AlertException">AlertException if the status of the Disruptor has changed.</exception>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier, TimeSpan timeout)
        {
            long availableSequence;
            var counter = 0;
            var sw = Stopwatch.StartNew();

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    counter = ApplyWaitMethod(barrier, counter);
                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    counter = ApplyWaitMethod(barrier, counter);
                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }

            return availableSequence;
        }
示例#15
0
        public override long waitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            long availableSequence;
            if ((availableSequence = cursor.get()) < sequence)
            {
                lock (_lock)
                {

                    try
                    {
                        ++numWaiters;
                        while ((availableSequence = cursor.get()) < sequence)
                        {
                            barrier.checkAlert();
                            Monitor.Wait(_lock);
                        }
                    }
                    finally
                    {
                        --numWaiters;
                    }
                }
            }

            if (0 != dependents.Length)
            {
                while ((availableSequence = Util.getMinimumSequence(dependents)) < sequence)
                {
                    barrier.checkAlert();
                }
            }

            return availableSequence;
        }
        public long WaitFor(
            long sequence,
            ISequence cursor,
            ISequence dependentSequence,
            ISequenceBarrier barrier)
        {
            var timeoutInMillis = _timeoutInMillis;

            if (cursor.GetValue() < sequence)
            {
                lock (_mutex)
                {
                    while (cursor.GetValue() < sequence)
                    {
                        barrier.CheckAlert();
                        if (!Monitor.Wait(_mutex, timeoutInMillis))
                        {
                            throw new TimeoutException();
                        }
                    }
                }
            }

            long availableSequence;

            while ((availableSequence = dependentSequence.GetValue()) < sequence)
            {
                barrier.CheckAlert();
            }

            return(availableSequence);
        }
        /// <summary>
        /// Wait for the given sequence to be available with a timeout specified.
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the processor is waiting on.</param>
        /// <param name="timeout">timeout value to abort after.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        /// <exception cref="AlertException">AlertException if the status of the Disruptor has changed.</exception>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier,
                        TimeSpan timeout)
        {
            long availableSequence;
            if ((availableSequence = cursor.Value) < sequence)
            {
                Monitor.Enter(_gate);
                try
                {
                    while ((availableSequence = cursor.Value) < sequence)
                    {
                        barrier.CheckAlert();

                        if (!Monitor.Wait(_gate, timeout))
                        {
                            break;
                        }
                    }
                }
                finally
                {
                    Monitor.Exit(_gate);
                }
            }

            if (dependents.Length != 0)
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                }
            }

            return availableSequence;
        }
示例#18
0
        public Ring_Buffer_Test()
        {
            _ringBuffer = RingBuffer <StubEvent> .CreateMultiProducer(StubEvent.EventFactory, 32);

            _barrier = _ringBuffer.NewBarrier();
            _ringBuffer.AddGatingSequences(new NoOpEventProcessor <StubEvent>(_ringBuffer).GetSequence());
        }
示例#19
0
 public EventProcessorInfo(IEventProcessor eventProcessor, object eventHandler, ISequenceBarrier barrier)
 {
     EventProcessor = eventProcessor;
     Handler        = eventHandler;
     Barrier        = barrier;
     IsEndOfChain   = true;
 }
        public Batch_Event_Processor_Test(ObjectContainerFixture provider)
        {
            _ringBuffer = RingBuffer <StubEvent> .CreateMultiProducer(StubEvent.EventFactory, 16);

            _barrier          = _ringBuffer.NewBarrier();
            _exceptionHandler = provider.Services.GetService <IExceptionHandler <StubEvent> >();
        }
 public TimeoutBlockingWaitStrategyTest()
 {
     _barrier   = new DummySequenceBarrier();
     _strategy  = new TimeoutBlockingWaitStrategy(TimeoutMilliseconds);
     _cursor    = new Sequence(5);
     _dependent = _cursor;
 }
        public OneToThreeSequencedThroughputTest()
            : base(Test_Disruptor, ITERATIONS,7)
        {
            ThreadPool.SetMaxThreads(NUM_EVENT_PROCESSORS,NUM_EVENT_PROCESSORS);
            for (long i = 0; i < ITERATIONS; i++)
            {
                results[0] = Operation.Addition.Op(results[0], i);
                results[1] = Operation.Substraction.Op(results[1], i);
                results[2] = Operation.And.Op(results[2], i);
            }
            sequenceBarrier = ringBuffer.NewBarrier();

            handlers[0] = new ValueMutationEventHandler_v3(Operation.Addition);
            handlers[1] = new ValueMutationEventHandler_v3(Operation.Substraction);
            handlers[2] = new ValueMutationEventHandler_v3(Operation.And);

            batchEventProcessors[0] = new BatchEventProcessor<ValueEvent>(ringBuffer, sequenceBarrier, handlers[0]);
            batchEventProcessors[1] = new BatchEventProcessor<ValueEvent>(ringBuffer, sequenceBarrier, handlers[1]);
            batchEventProcessors[2] = new BatchEventProcessor<ValueEvent>(ringBuffer, sequenceBarrier, handlers[2]);

            ringBuffer.AddGatingSequences(
                                     batchEventProcessors[0].Sequence,
                                     batchEventProcessors[1].Sequence,
                                     batchEventProcessors[2].Sequence);
        }
示例#23
0
        /// <summary>
        /// Wait for the given sequence to be available with a timeout specified.
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the processor is waiting on.</param>
        /// <param name="timeout">timeout value to abort after.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        /// <exception cref="AlertException">AlertException if the status of the Disruptor has changed.</exception>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier, TimeSpan timeout)
        {
            long availableSequence;
            var  counter = SpinTries;
            var  sw      = Stopwatch.StartNew();

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    counter = ApplyWaitMethod(barrier, counter);
                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    counter = ApplyWaitMethod(barrier, counter);
                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }

            return(availableSequence);
        }
示例#24
0
        /// <summary>
        /// Construct a <see cref="WorkProcessor{T}"/>.
        /// </summary>
        /// <param name="ringBuffer">to which events are published.</param>
        /// <param name="barrier">on which it is waiting.</param>
        /// <param name="workHandler">is the delegate to which events are dispatched.</param>
        /// <param name="exceptionHandler">to be called back when an error occurs.</param>
        /// <param name="workSequence">from which to claim the next event to be worked on. It should always be initialised <see cref="Sequence.InitialValue"/></param>
        public WorkProcessor(
            RingBuffer <T> ringBuffer,
            ISequenceBarrier barrier,
            IWorkHandler <T> workHandler,
            IExceptionHandler <T> exceptionHandler,
            ISequence workSequence)
        {
            _ringBuffer       = ringBuffer;
            _barrier          = barrier;
            _workHandler      = workHandler;
            _exceptionHandler = exceptionHandler;
            _workSequence     = workSequence;
            _sequence         = new Sequence();

            if (_workHandler is ITimeoutHandler timeoutHandler)
            {
                _timeoutHandler = timeoutHandler;
            }

            if (_workHandler is ILifecycleAware lifecycleAware)
            {
                _lifecycleAware = lifecycleAware;
            }

            if (_workHandler is IEventReleaseAware eventReleaseAware)
            {
                _eventReleaser = new EventReleaser(_sequence);
                eventReleaseAware.SetEventReleaser(_eventReleaser);
            }
        }
 public EventProcessorInfo(IEventProcessor eventProcessor, IEventHandler <T> eventHandler, ISequenceBarrier sequenceBarrier)
 {
     EventProcessor  = eventProcessor;
     EventHandler    = eventHandler;
     SequenceBarrier = sequenceBarrier;
     IsEndOfChain    = true;
 }
        /// <summary>
        /// Wait for the given sequence to be available
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">Ring buffer cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the <see cref="IEventProcessor"/> is waiting on.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            var availableSequence = cursor.Value; // volatile read

            if (availableSequence < sequence)
            {
                Monitor.Enter(_gate);
                try
                {
                    ++_numWaiters;
                    while ((availableSequence = cursor.Value) < sequence) // volatile read
                    {
                        barrier.CheckAlert();
                        Monitor.Wait(_gate);
                    }
                }
                finally
                {
                    --_numWaiters;
                    Monitor.Exit(_gate);
                }
            }

            if (dependents.Length != 0)
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                }
            }

            return(availableSequence);
        }
        /// <summary>
        /// Wait for the given sequence to be available with a timeout specified.
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the processor is waiting on.</param>
        /// <param name="timeout">timeout value to abort after.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        /// <exception cref="AlertException">AlertException if the status of the Disruptor has changed.</exception>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier, TimeSpan timeout)
        {
            long availableSequence;
            var spinWait = default(SpinWait);
            var sw = Stopwatch.StartNew();

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();

                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                    spinWait.SpinOnce();

                    if (sw.Elapsed > timeout)
                    {
                        break;
                    }
                }
            }

            return availableSequence;
        }
        /// <summary>
        ///  Construct a <see cref="IBatchEventProcessor{TEvent}"/> that will automatically track the progress by updating its sequence when the <see cref="IEventHandler{TEvent}.OnEvent(TEvent,long,bool)"/> method returns.
        /// </summary>
        /// <param name="exceptionHandler"></param>
        /// <param name="dataProvider">to which events are published.</param>
        /// <param name="sequenceBarrier">on which it is waiting.</param>
        /// <param name="eventHandler">is the delegate to which events are dispatched.</param>
        public BatchEventProcessor(
            IDataProvider <TEvent> dataProvider,
            ISequenceBarrier sequenceBarrier,
            IEventHandler <TEvent> eventHandler,
            IExceptionHandler <TEvent> exceptionHandler)
        {
            _exceptionHandler = exceptionHandler;
            _dataProvider     = dataProvider;
            _sequenceBarrier  = sequenceBarrier;
            _eventHandler     = eventHandler;
            _sequence         = new Sequence();

            if (eventHandler is ISequenceReportingEventHandler <TEvent> reporting)
            {
                reporting?.SetSequenceCallback(_sequence);
            }

            if (eventHandler is IBatchStartAware batchStartAware)
            {
                _batchStartAware = batchStartAware;
            }

            if (eventHandler is ITimeoutHandler timeoutHandler)
            {
                _timeoutHandler = timeoutHandler;
            }

            if (eventHandler is ILifecycleAware lifecycleAware)
            {
                _lifecycleAware = lifecycleAware;
            }
        }
示例#29
0
        public long Start()
        {
            OzzyLogger <IDomainModelTracing> .Log.TraceInformationalEvent("Start event loop");

            if (Interlocked.CompareExchange(ref _stage, 1, 0) == 0)
            {
                var minCheckpoint = 0L;
                var checkpoints   = _eventProcessors.Select(e => e.GetCheckpoint()).ToList();
                if (checkpoints.Any())
                {
                    minCheckpoint = checkpoints.Min();
                }

                _disruptor = new Disruptor <DomainEventEntry>(() => new DomainEventEntry(),
                                                              new MultiThreadedClaimStrategy(_bufferSize),
                                                              _waitStrategy ?? new BlockingWaitStrategy(),
                                                              TaskScheduler.Default,
                                                              minCheckpoint);
                _disruptor.HandleExceptionsWith(_exceptionHandler);
                foreach (var domainEventsProcessor in _eventProcessors)
                {
                    _disruptor.HandleEventsWith(domainEventsProcessor.GetCheckpoint(), domainEventsProcessor);
                }
                _ringBuffer = _disruptor.Start();
                _barrier    = _ringBuffer.NewBarrier();
                StartCursorSupervisor(minCheckpoint, TimeSpan.FromMilliseconds(_pollTimeout));
                Interlocked.Exchange(ref _stage, 2);
                return(minCheckpoint);
            }
            else
            {
                throw new InvalidOperationException("Domain Manager already started");
            }
        }
        private IEventProcessor[] GetRequestSenders(
            RingBuffer <EventType> ringBuffer,
            ISequenceBarrier sequenceBarrier,
            RequestSenderMode mode)
        {
            var mockExternalService = new MockExternalService <OutgoingRequest, int>();

            AsyncExtensions.FireAndForgetLongRunning(
                () => mockExternalService.Run(),
                (ex) => Assert.Fail(ex.StackTrace)
                );

            var createOrUpdateRequestExecutor = new RequestSender <EventType, OutgoingRequest>(
                (@event) => @event.CreateOrUpdateTodoListRequest, mockExternalService, mode, (ex) => Assert.Fail(ex.StackTrace)
                );
            var deleteRequestExecutor = new RequestSender <EventType, OutgoingRequest>(
                (@event) => @event.DeleteTodoListsRequest, mockExternalService, mode, (ex) => Assert.Fail(ex.StackTrace)
                );
            var removeItemsRequestExecutor = new RequestSender <EventType, OutgoingRequest>(
                (@event) => @event.RemoveLineItemsRequest, mockExternalService, mode, (ex) => Assert.Fail(ex.StackTrace)
                );

            return(new IEventProcessor[] {
                new AsyncEventProcessor <EventType>(
                    ringBuffer, sequenceBarrier, new SpinLock(), createOrUpdateRequestExecutor
                    ),
                new AsyncEventProcessor <EventType>(
                    ringBuffer, sequenceBarrier, new SpinLock(), deleteRequestExecutor
                    ),
                new AsyncEventProcessor <EventType>(
                    ringBuffer, sequenceBarrier, new SpinLock(), removeItemsRequestExecutor
                    ),
            });
        }
示例#31
0
 public TestWaiter(Barrier barrier, ISequenceBarrier sequenceBarrier, RingBuffer <StubEvent> ringBuffer, long initialSequence, long toWaitForSequence)
 {
     _barrier           = barrier;
     _sequenceBarrier   = sequenceBarrier;
     _ringBuffer        = ringBuffer;
     _initialSequence   = initialSequence;
     _toWaitForSequence = toWaitForSequence;
 }
示例#32
0
        public void Add(IEventProcessor eventProcessor, object eventHandler, ISequenceBarrier sequenceBarrier)
        {
            var consumerInfo = new EventProcessorInfo(eventProcessor, eventHandler, sequenceBarrier);

            _eventProcessorInfoByEventHandler[eventHandler]        = consumerInfo;
            _eventProcessorInfoBySequence[eventProcessor.Sequence] = consumerInfo;
            _consumerInfos.Add(consumerInfo);
        }
示例#33
0
 public TestWaiter(Barrier barrier, ISequenceBarrier sequenceBarrier, RingBuffer<StubEvent> ringBuffer, long initialSequence, long toWaitForSequence)
 {
     _barrier = barrier;
     _sequenceBarrier = sequenceBarrier;
     _ringBuffer = ringBuffer;
     _initialSequence = initialSequence;
     _toWaitForSequence = toWaitForSequence;
 }
        public BatchEventProcessorBenchmarks()
        {
            _ringBuffer      = new RingBuffer <TestEvent>(() => new TestEvent(), new SingleProducerSequencer(4096, new SpinWaitWaitStrategy()));
            _eventHandler    = new TestEventHandler();
            _sequenceBarrier = _ringBuffer.NewBarrier();

            _ringBuffer.PublishEvent().Dispose();
        }
 public OneToOneSequencedBatchThroughputTest()
     : base(Test_Disruptor, ITERATIONS, 7)
 {
     ThreadPool.SetMaxThreads(4, 4);
     sequenceBarrier     = ringBuffer.NewBarrier();
     batchEventProcessor = new BatchEventProcessor <ValueEvent>(ringBuffer, sequenceBarrier, handler);
     ringBuffer.AddGatingSequences(batchEventProcessor.Sequence);
 }
 public OneToOneSequencedLongArrayThroughputTest()
     : base(Test_Disruptor, ITERATIONS,7)
 {
     ThreadPool.SetMaxThreads (1,1);
     sequenceBarrier = ringBuffer.NewBarrier();
     batchEventProcessor = new BatchEventProcessor<long[]>(ringBuffer, sequenceBarrier, handler);
     ringBuffer.AddGatingSequences(batchEventProcessor.Sequence);
 }
示例#37
0
 /// <summary>
 /// Construct a <see cref="WorkProcessor{T}"/>.
 /// </summary>
 /// <param name="ringBuffer">ringBuffer to which events are published.</param>
 /// <param name="sequenceBarrier">sequenceBarrier on which it is waiting.</param>
 /// <param name="workHandler">workHandler is the delegate to which events are dispatched.</param>
 /// <param name="exceptionHandler">exceptionHandler to be called back when an error occurs</param>
 /// <param name="workSequence">workSequence from which to claim the next event to be worked on.  It should always be initialised
 /// as <see cref="Sequencer.InitialCursorValue"/></param>
 public WorkProcessor(RingBuffer <T> ringBuffer, ISequenceBarrier sequenceBarrier, IWorkHandler <T> workHandler, IExceptionHandler exceptionHandler, Sequence workSequence)
 {
     _ringBuffer       = ringBuffer;
     _sequenceBarrier  = sequenceBarrier;
     _workHandler      = workHandler;
     _exceptionHandler = exceptionHandler;
     _workSequence     = workSequence;
 }
示例#38
0
        public OnePublisherToOneProcessorUniCastThroughputTest()
            : base("Disruptor", ITERATIONS)
        {
            sequenceBarrier     = ringBuffer.NewBarrier();
            batchEventProcessor = new BatchEventProcessor <ValueEvent>(ringBuffer, sequenceBarrier, disruptorHandler);
            ringBuffer.AddGatingSequences(batchEventProcessor.Sequence);

            //queueHandler = new ValueAdditionQueueProcessor_V3(blockQueue, ITERATIONS - 1);
        }
        public OnePublisherToOneProcessorUniCastThroughputTest()
            : base("Disruptor", ITERATIONS)
        {
            sequenceBarrier = ringBuffer.NewBarrier();
            batchEventProcessor = new BatchEventProcessor<ValueEvent>(ringBuffer, sequenceBarrier, disruptorHandler);
            ringBuffer.AddGatingSequences(batchEventProcessor.Sequence);

            //queueHandler = new ValueAdditionQueueProcessor_V3(blockQueue, ITERATIONS - 1);
        }
示例#40
0
 public void Setup()
 {
     _ringBuffer          = new RingBuffer <StubEvent>(() => new StubEvent(-1), 16);
     _sequenceBarrier     = _ringBuffer.NewBarrier();
     _batchHandlerMock    = new Mock <IEventHandler <StubEvent> >();
     _countDownEvent      = new CountdownEvent(1);
     _batchEventProcessor = new BatchEventProcessor <StubEvent>(_ringBuffer, _sequenceBarrier, _batchHandlerMock.Object);
     _ringBuffer.AddGatingSequences(_batchEventProcessor.Sequence);
 }
示例#41
0
 public RingBufferConsumer(
     IRingBuffer <TMessage> messageQueue,
     ISequenceBarrier sequenceBarrier,
     IMessageHandler <TMessage> batchMessageHandler)
 {
     this._messageBuffer       = messageQueue;
     this._sequenceBarrier     = sequenceBarrier;
     this._batchMessageHandler = batchMessageHandler;
 }
示例#42
0
 public EventProcessorInfo(
     IEventProcessor processor,
     IEventHandler <T> handler,
     ISequenceBarrier barrier)
 {
     _processor = processor;
     _handler   = handler;
     _barrier   = barrier;
 }
 public void Setup()
 {
     _ringBuffer = new RingBuffer<StubEvent>(()=>new StubEvent(-1), 16);
     _sequenceBarrier = _ringBuffer.NewBarrier();
     _batchHandlerMock = new Mock<IEventHandler<StubEvent>>();
     _countDownEvent = new CountdownEvent(1);
     _batchEventProcessor = new BatchEventProcessor<StubEvent>(_ringBuffer, _sequenceBarrier, _batchHandlerMock.Object);
     _ringBuffer.AddGatingSequences(_batchEventProcessor.Sequence);
 }
示例#44
0
        /// <summary>
        /// Construct a <see cref="BatchEventProcessor{T}"/> that will automatically track the progress by updating its sequence when
        /// the <see cref="IEventHandler{T}.OnEvent"/> method returns.
        /// </summary>
        /// <param name="dataProvider">dataProvider to which events are published</param>
        /// <param name="sequenceBarrier">SequenceBarrier on which it is waiting.</param>
        /// <param name="eventHandler">eventHandler is the delegate to which events are dispatched.</param>
        public BatchEventProcessor(IDataProvider <T> dataProvider, ISequenceBarrier sequenceBarrier, IEventHandler <T> eventHandler)
        {
            _dataProvider    = dataProvider;
            _sequenceBarrier = sequenceBarrier;
            _eventHandler    = eventHandler;

            (eventHandler as ISequenceReportingEventHandler <T>)?.SetSequenceCallback(_sequence);
            _timeoutHandler = eventHandler as ITimeoutHandler;
        }
 public ThreeToOneSequencedThroughputTest()
 {
     _sequenceBarrier = _ringBuffer.NewBarrier();
     _batchEventProcessor = new BatchEventProcessor<ValueEvent>(_ringBuffer, _sequenceBarrier, _handler);
     for (var i = 0; i < _numPublishers; i++)
     {
         _valuePublishers[i] = ValuePublisher;
     }
     _ringBuffer.AddGatingSequences(_batchEventProcessor.Sequence);
 }
        /// <summary>
        /// <see cref="IWaitStrategy.WaitFor"/>
        /// </summary>
        public long WaitFor(long sequence, Sequence cursor, ISequence dependentSequence, ISequenceBarrier barrier)
        {
            long availableSequence;

            while ((availableSequence = dependentSequence.Value) < sequence)
            {
                barrier.CheckAlert();
            }

            return availableSequence;
        }
示例#47
0
 public TestWaiter(CyclicBarrier cyclicBarrier,
     ISequenceBarrier sequenceBarrier,
     RingBuffer<StubEvent> ringBuffer,
     long initialSequence,
     long toWaitForSequence)
 {
     this.cyclicBarrier = cyclicBarrier;
     this.initialSequence = initialSequence;
     this.ringBuffer = ringBuffer;
     this.toWaitForSequence = toWaitForSequence;
     this.sequenceBarrier = sequenceBarrier;
 }
        /// <summary>
        /// Wait for the given sequence to be available.  It is possible for this method to return a value
        /// less than the sequence number supplied depending on the implementation of the WaitStrategy.  A common
        /// use for this is to signal a timeout.  Any EventProcessor that is using a WaitStragegy to get notifications
        /// about message becoming available should remember to handle this case.  The {@link BatchEventProcessor} explicitly
        /// handles this case and will signal a timeout if required.
        /// </summary>
        /// <param name="sequence">to be waited on.</param>
        /// <param name="cursor">the main sequence from ringbuffer. Wait/notify strategies will need this as it's the only sequence that is also notified upon update.</param>
        /// <param name="dependentSequence">on which to wait.</param>
        /// <param name="barrier">the processor is waiting on.</param>
        /// <returns></returns>
        /// <exception cref="AlertException">if the status of the Disruptor has changed.</exception>
        /// <exception cref="System.Threading.ThreadInterruptedException">if the thread is interrupted.</exception>
        /// <exception cref="TimeoutException"></exception>
        /// Date:2013/8/27   
        /// Author:liguo
        public long WaitFor(long sequence, Sequence cursor, Sequence dependentSequence, ISequenceBarrier barrier)
        {
            long availableSequence;
            int counter = RETRIES;

            while ((availableSequence = dependentSequence.Value) < sequence)
            {
                counter = ApplyWaitMethod(barrier, counter);
            }

            return availableSequence;
        }
        public ThreeToOneSequencedBatchThroughputTest()
            : base(Test_Disruptor, ITERATIONS,7)
        {
            ThreadPool.SetMaxThreads (4,4);
            sequenceBarrier = ringBuffer.NewBarrier();
            batchEventProcessor = new BatchEventProcessor<ValueEvent>(ringBuffer, sequenceBarrier, handler);

            for (int i = 0; i < NUM_PUBLISHERS; i++)
            {
                valuePublishers[i] = new ValueBatchPublisher(cyclicBarrier, ringBuffer, ITERATIONS / NUM_PUBLISHERS, 10);
            }
            ringBuffer.AddGatingSequences(batchEventProcessor.Sequence);
        }
        private int ApplyWaitMethod(ISequenceBarrier barrier, int counter)
        {
            barrier.CheckAlert();

            if (0 == counter)
            {               
                Thread.Yield ();
            }
            else
            {
                --counter;
            }

            return counter;
        }
 public TwoPublisherToTwoProcessorWorkProcessorThroughputTest()
     : base(TestName, ITERATIONS)
 {
     sequenceBarrier = ringBuffer.NewBarrier();
     workProcessors[0] = new WorkProcessor<ValueEvent>(ringBuffer, sequenceBarrier,
                                                handlers[0], new IgnoreExceptionHandler(),
                                                workSequence);
     workProcessors[1] = new WorkProcessor<ValueEvent>(ringBuffer, sequenceBarrier,
                                                      handlers[1], new IgnoreExceptionHandler(),
                                                      workSequence);
     //workerPool = new WorkerPool<ValueEvent>(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), handlers);
     for (int i = 0; i < NUM_PUBLISHERS; i++)
     {
         valuePublishers[i] = new ValuePublisher_V3(cyclicBarrier, ringBuffer, ITERATIONS);
     }
     workProcessors.ToList().ForEach(e => ringBuffer.AddGatingSequences(e.Sequence));
     //ringBuffer.AddGatingSequences(/*workerPool.getWorkerSequences()*/workProcessors[0].Sequence, workProcessors[1].Sequence);
 }
        private static int ApplyWaitMethod(ISequenceBarrier barrier, int counter)
        {
            barrier.CheckAlert();

            if (counter > 100)
            {
                --counter;
            }
            else if (counter > 0)
            {
                --counter;
                Thread.Yield();
            }
            else
            {
                Thread.Sleep(0);
            }

            return counter;
        }
        /// <summary>
        /// Wait for the given sequence to be available
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">Ring buffer cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the <see cref="IEventProcessor"/> is waiting on.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            long availableSequence;

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    barrier.CheckAlert();
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    barrier.CheckAlert();
                }
            }

            return availableSequence;
        }
        private int ApplyWaitMethod(ISequenceBarrier barrier, int counter)
        {
            barrier.CheckAlert();

            if (counter > 100)
            {
                --counter;
            }
            else if (counter > 0)
            {
                --counter;
                Thread.Sleep(0);
            }
            else
            {              
                spinWait.SpinOnce();
                //LockSupport.parkNanos(1L);
            }

            return counter;
        }
        /// <summary>
        /// <see cref="IWaitStrategy.WaitFor"/>
        /// </summary>
        public long WaitFor(long sequence, Sequence cursor, ISequence dependentSequence, ISequenceBarrier barrier)
        {
            if (cursor.Value < sequence)
            {
                lock (_gate)
                {
                    while (cursor.Value < sequence)
                    {
                        barrier.CheckAlert();
                        Monitor.Wait(_gate);
                    }
                }
            }

            long availableSequence;
            while ((availableSequence = dependentSequence.Value) < sequence)
            {
                barrier.CheckAlert();
            }

            return availableSequence;
        }
        /// <summary>
        /// Wait for the given sequence to be available
        /// </summary>
        /// <param name="sequence">sequence to be waited on.</param>
        /// <param name="cursor">Ring buffer cursor on which to wait.</param>
        /// <param name="dependents">dependents further back the chain that must advance first</param>
        /// <param name="barrier">barrier the <see cref="IEventProcessor"/> is waiting on.</param>
        /// <returns>the sequence that is available which may be greater than the requested sequence.</returns>
        public long WaitFor(long sequence, Sequence cursor, Sequence[] dependents, ISequenceBarrier barrier)
        {
            long availableSequence;
            var counter = 0;

            if (dependents.Length == 0)
            {
                while ((availableSequence = cursor.Value) < sequence) // volatile read
                {
                    counter = ApplyWaitMethod(barrier, counter);
                }
            }
            else
            {
                while ((availableSequence = Util.GetMinimumSequence(dependents)) < sequence)
                {
                    counter = ApplyWaitMethod(barrier, counter);
                }
            }

            return availableSequence;
        }
        public TwoToTwoWorkProcessorThroughputTest()
            : base(Test_Disruptor, ITERATIONS)
        {
            sequenceBarrier = ringBuffer.NewBarrier();
            handlers[0] = new ValueAdditionWorkHandler();
            handlers[1] = new ValueAdditionWorkHandler();

            workProcessors[0] = new WorkProcessor<ValueEvent>(ringBuffer, sequenceBarrier,
                                                    handlers[0], new IgnoreExceptionHandler(),
                                                    workSequence);
            workProcessors[1] = new WorkProcessor<ValueEvent>(ringBuffer, sequenceBarrier,
                                                             handlers[1], new IgnoreExceptionHandler(),
                                                             workSequence);

            for (int i = 0; i < NUM_PUBLISHERS; i++)
            {
                valuePublishers[i] = new ValuePublisher(cyclicBarrier, ringBuffer, ITERATIONS);
            }

            ringBuffer.AddGatingSequences(workProcessors[0].Sequence, workProcessors[1].Sequence);

        }
        public long WaitFor(long sequence, Sequence cursor, Sequence dependentSequence, ISequenceBarrier barrier)
        {
            long availableSequence;
            if ((availableSequence = dependentSequence.Value) < sequence)
            {
                bool lockToken = false;
                Monitor.Enter(obj, ref lockToken);
                try
                {
                    do
                    {
                        signalNeeded.WriteFullFence(true);

                        if ((availableSequence = dependentSequence.Value) >= sequence)
                        {
                            break;
                        }

                        barrier.CheckAlert();
                        Monitor.Wait(obj);
                    }
                    while ((availableSequence = dependentSequence.Value) < sequence);
                }
                finally
                {
                    if (lockToken)
                        Monitor.Exit(obj);
                }
            }

            while ((availableSequence = dependentSequence.Value) < sequence)
            {
                barrier.CheckAlert();
            }

            return availableSequence;
        }
        /// <summary>
        /// Wait for the given sequence to be available.  It is possible for this method to return a value
        /// less than the sequence number supplied depending on the implementation of the WaitStrategy.  A common
        /// use for this is to signal a timeout.  Any EventProcessor that is using a WaitStragegy to get notifications
        /// about message becoming available should remember to handle this case.  The {@link BatchEventProcessor} explicitly
        /// handles this case and will signal a timeout if required.
        /// </summary>
        /// <param name="sequence">to be waited on.</param>
        /// <param name="cursor">the main sequence from ringbuffer. Wait/notify strategies will need this as it's the only sequence that is also notified upon update.</param>
        /// <param name="dependentSequence">on which to wait.</param>
        /// <param name="barrier">the processor is waiting on.</param>
        /// <returns></returns>
        /// <exception cref="AlertException">if the status of the Disruptor has changed.</exception>
        /// <exception cref="System.Threading.ThreadInterruptedException">if the thread is interrupted.</exception>
        /// <exception cref="TimeoutException"></exception>
        /// Date:2013/8/27   
        /// Author:liguo
        public long WaitFor(long sequence, Sequence cursor, Sequence dependentSequence, ISequenceBarrier barrier)
        {
            long availableSequence;
            long startTime = 0;
            int counter = SPIN_TRIES;
            var stopWatch = Stopwatch.StartNew();
            do
            {
                if ((availableSequence = dependentSequence.Value) >= sequence)
                {
                    return availableSequence;
                }

                if (0 == --counter)
                {
                    if (0 == startTime)
                    {
                        startTime = stopWatch.ElapsedTicks;
                    }
                    else
                    {
                        var timeDelta = stopWatch.Elapsed;
                        if (timeDelta > yieldTimeoutNanos)
                        {
                            return lockingStrategy.WaitOnLock(sequence, cursor, dependentSequence, barrier, spinTimeoutNanos);
                        }
                        else if (timeDelta > spinTimeoutNanos)
                        {
                            Thread.Sleep(0);
                        }
                    }
                    counter = SPIN_TRIES;
                }
            }
            while (true);
        }
 public MyRunnable(ISequencer sequencer)
 {
     _barrier = sequencer.NewBarrier();
 }